Subversion Repositories Kolibri OS

Rev

Rev 4433 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 4424 $
  9.  
  10.  
  11. align 4
  12. proc alloc_page
  13.  
  14.         pushfd
  15.         cli
  16.         push    ebx
  17. ;//-
  18.         cmp     [pg_data.pages_free], 1
  19.         jle     .out_of_memory
  20. ;//-
  21.  
  22.         mov     ebx, [page_start]
  23.         mov     ecx, [page_end]
  24. .l1:
  25.         bsf     eax, [ebx];
  26.         jnz     .found
  27.         add     ebx, 4
  28.         cmp     ebx, ecx
  29.         jb      .l1
  30.         pop     ebx
  31.         popfd
  32.         xor     eax, eax
  33.         ret
  34. .found:
  35. ;//-
  36.         dec     [pg_data.pages_free]
  37.         jz      .out_of_memory
  38. ;//-
  39.         btr     [ebx], eax
  40.         mov     [page_start], ebx
  41.         sub     ebx, sys_pgmap
  42.         lea     eax, [eax+ebx*8]
  43.         shl     eax, 12
  44. ;//-       dec [pg_data.pages_free]
  45.         pop     ebx
  46.         popfd
  47.         ret
  48. ;//-
  49. .out_of_memory:
  50.         mov     [pg_data.pages_free], 1
  51.         xor     eax, eax
  52.         pop     ebx
  53.         popfd
  54.         ret
  55. ;//-
  56. endp
  57.  
  58. align 4
  59. proc alloc_pages stdcall, count:dword
  60.         pushfd
  61.         push    ebx
  62.         push    edi
  63.         cli
  64.         mov     eax, [count]
  65.         add     eax, 7
  66.         shr     eax, 3
  67.         mov     [count], eax
  68. ;//-
  69.         mov     ebx, [pg_data.pages_free]
  70.         sub     ebx, 9
  71.         js      .out_of_memory
  72.         shr     ebx, 3
  73.         cmp     eax, ebx
  74.         jg      .out_of_memory
  75. ;//-
  76.         mov     ecx, [page_start]
  77.         mov     ebx, [page_end]
  78. .find:
  79.         mov     edx, [count]
  80.         mov     edi, ecx
  81. .match:
  82.         cmp     byte [ecx], 0xFF
  83.         jne     .next
  84.         dec     edx
  85.         jz      .ok
  86.         inc     ecx
  87.         cmp     ecx, ebx
  88.         jb      .match
  89. .out_of_memory:
  90. .fail:
  91.         xor     eax, eax
  92.         pop     edi
  93.         pop     ebx
  94.         popfd
  95.         ret
  96. .next:
  97.         inc     ecx
  98.         cmp     ecx, ebx
  99.         jb      .find
  100.         pop     edi
  101.         pop     ebx
  102.         popfd
  103.         xor     eax, eax
  104.         ret
  105. .ok:
  106.         sub     ecx, edi
  107.         inc     ecx
  108.         push    esi
  109.         mov     esi, edi
  110.         xor     eax, eax
  111.         rep stosb
  112.         sub     esi, sys_pgmap
  113.         shl     esi, 3+12
  114.         mov     eax, esi
  115.         mov     ebx, [count]
  116.         shl     ebx, 3
  117.         sub     [pg_data.pages_free], ebx
  118.         pop     esi
  119.         pop     edi
  120.         pop     ebx
  121.         popfd
  122.         ret
  123. endp
  124.  
  125. align 4
  126. ;proc map_page stdcall,lin_addr:dword,phis_addr:dword,flags:dword
  127. map_page:
  128.         push    ebx
  129.         mov     eax, [esp+12]               ; phis_addr
  130.         and     eax, not 0xFFF
  131.         or      eax, [esp+16]              ; flags
  132.         mov     ebx, [esp+8]               ; lin_addr
  133.         shr     ebx, 12
  134.         mov     [page_tabs+ebx*4], eax
  135.         mov     eax, [esp+8]               ; lin_addr
  136.         pop     ebx
  137.         invlpg  [eax]
  138.         ret     12
  139.  
  140. align 4
  141. map_space:    ;not implemented
  142.  
  143.  
  144.         ret
  145.  
  146.  
  147. align 4
  148. proc free_page
  149. ;arg:  eax  page address
  150.         pushfd
  151.         cli
  152.         shr     eax, 12                       ;page index
  153.         bts     dword [sys_pgmap], eax        ;that's all!
  154.         cmc
  155.         adc     [pg_data.pages_free], 0
  156.         shr     eax, 3
  157.         and     eax, not 3                    ;dword offset from page_map
  158.         add     eax, sys_pgmap
  159.         cmp     [page_start], eax
  160.         ja      @f
  161.         popfd
  162.         ret
  163. @@:
  164.         mov     [page_start], eax
  165.         popfd
  166.         ret
  167. endp
  168.  
  169. align 4
  170. proc map_io_mem stdcall, base:dword, size:dword, flags:dword
  171.  
  172.         push    ebx
  173.         push    edi
  174.         mov     eax, [size]
  175.         add     eax, [base]
  176.         add     eax, 4095
  177.         and     eax, -4096
  178.         mov     ecx, [base]
  179.         and     ecx, -4096
  180.         sub     eax, ecx
  181.         mov     [size], eax
  182.  
  183.         stdcall alloc_kernel_space, eax
  184.         test    eax, eax
  185.         jz      .fail
  186.         push    eax
  187.  
  188.         mov     edi, 0x1000
  189.         mov     ebx, eax
  190.         mov     ecx, [size]
  191.         mov     edx, [base]
  192.         shr     eax, 12
  193.         shr     ecx, 12
  194.         and     edx, -4096
  195.         or      edx, [flags]
  196. @@:
  197.         mov     [page_tabs+eax*4], edx
  198.         invlpg  [ebx]
  199.         inc     eax
  200.         add     ebx, edi
  201.         add     edx, edi
  202.         loop    @B
  203.  
  204.         pop     eax
  205.         mov     edx, [base]
  206.         and     edx, 4095
  207.         add     eax, edx
  208. .fail:
  209.         pop     edi
  210.         pop     ebx
  211.         ret
  212. endp
  213.  
  214. ; param
  215. ;  eax= page base + page flags
  216. ;  ebx= linear address
  217. ;  ecx= count
  218.  
  219. align 4
  220. commit_pages:
  221.         test    ecx, ecx
  222.         jz      .fail
  223.  
  224.         push    edi
  225.         push    eax
  226.         push    ecx
  227.         mov     ecx, pg_data.mutex
  228.         call    mutex_lock
  229.         pop     ecx
  230.         pop     eax
  231.  
  232.         mov     edi, ebx
  233.         shr     edi, 12
  234.         lea     edi, [page_tabs+edi*4]
  235.  
  236. if USE_FIX_FOR_INVALID_MS_VIRTUAL_PC_2007
  237.         mov     edx, eax
  238. @@:
  239.         mov     eax, edx
  240.         stosd
  241.         invlpg  [ebx]
  242.         add     edx, 0x1000
  243.         add     ebx, 0x1000
  244.         loop    @B
  245. else
  246. @@:
  247.         stosd
  248.         invlpg  [ebx]
  249.         add     eax, 0x1000
  250.         add     ebx, 0x1000
  251.         loop    @B
  252. end if
  253.  
  254.         pop     edi
  255.  
  256.         mov     ecx, pg_data.mutex
  257.         call    mutex_unlock
  258. .fail:
  259.         ret
  260.  
  261.  
  262. ; param
  263. ;  eax= base
  264. ;  ecx= count
  265.  
  266. align 4
  267. release_pages:
  268.  
  269.         push    ebp
  270.         push    esi
  271.         push    edi
  272.         push    ebx
  273.  
  274.         mov     esi, eax
  275.         mov     edi, eax
  276.  
  277.         shr     esi, 12
  278.         lea     esi, [page_tabs+esi*4]
  279.  
  280.         push    ecx
  281.         mov     ecx, pg_data.mutex
  282.         call    mutex_lock
  283.         pop     ecx
  284.  
  285.         mov     ebp, [pg_data.pages_free]
  286.         mov     ebx, [page_start]
  287.         mov     edx, sys_pgmap
  288. @@:
  289.         xor     eax, eax
  290.         xchg    eax, [esi]
  291.         invlpg  [edi]
  292.  
  293.         test    eax, 1
  294.         jz      .next
  295.  
  296.         shr     eax, 12
  297.         bts     [edx], eax
  298.         cmc
  299.         adc     ebp, 0
  300.         shr     eax, 3
  301.         and     eax, -4
  302.         add     eax, edx
  303.         cmp     eax, ebx
  304.         jae     .next
  305.  
  306.         mov     ebx, eax
  307. .next:
  308.         add     edi, 0x1000
  309.         add     esi, 4
  310.         loop    @B
  311.  
  312.         mov     [pg_data.pages_free], ebp
  313.         mov     ecx, pg_data.mutex
  314.         call    mutex_unlock
  315.  
  316.         pop     ebx
  317.         pop     edi
  318.         pop     esi
  319.         pop     ebp
  320.         ret
  321.  
  322. ; param
  323. ;  eax= base
  324. ;  ecx= count
  325.  
  326. align 4
  327. unmap_pages:
  328.  
  329.         push    edi
  330.  
  331.         mov     edi, eax
  332.         mov     edx, eax
  333.  
  334.         shr     edi, 10
  335.         add     edi, page_tabs
  336.  
  337.         xor     eax, eax
  338. @@:
  339.         stosd
  340.         invlpg  [edx]
  341.         add     edx, 0x1000
  342.         loop    @b
  343.  
  344.         pop     edi
  345.         ret
  346.  
  347.  
  348. align 4
  349. proc map_page_table stdcall, lin_addr:dword, phis_addr:dword
  350.         push    ebx
  351.         mov     ebx, [lin_addr]
  352.         shr     ebx, 22
  353.         mov     eax, [phis_addr]
  354.         and     eax, not 0xFFF
  355.         or      eax, PG_UW        ;+PG_NOCACHE
  356.         mov     dword [master_tab+ebx*4], eax
  357.         mov     eax, [lin_addr]
  358.         shr     eax, 10
  359.         add     eax, page_tabs
  360.         invlpg  [eax]
  361.         pop     ebx
  362.         ret
  363. endp
  364.  
  365. align 4
  366. proc init_LFB
  367.            locals
  368.              pg_count dd ?
  369.            endl
  370.  
  371.         cmp     dword [LFBAddress], -1
  372.         jne     @f
  373.         mov     [BOOT_VARS+BOOT_MTRR], byte 2
  374. ; max VGA=640*480*4=1228800 bytes
  375. ; + 32*640*4=81920 bytes for mouse pointer
  376.         stdcall alloc_pages, ((1228800+81920)/4096)
  377.  
  378.         push    eax
  379.         call    alloc_page
  380.         stdcall map_page_table, LFB_BASE, eax
  381.         pop     eax
  382.         or      eax, PG_UW
  383.         mov     ebx, LFB_BASE
  384. ; max VGA=640*480*4=1228800 bytes
  385. ; + 32*640*4=81920 bytes for mouse pointer
  386.         mov     ecx, (1228800+81920)/4096
  387.         call    commit_pages
  388.         mov     [LFBAddress], dword LFB_BASE
  389.         ret
  390. @@:
  391.         test    [SCR_MODE], word 0100000000000000b
  392.         jnz     @f
  393.         mov     [BOOT_VARS+BOOT_MTRR], byte 2
  394.         ret
  395. @@:
  396.         call    init_mtrr
  397.  
  398.         mov     edx, LFB_BASE
  399.         mov     esi, [LFBAddress]
  400.         mov     edi, 0x00C00000
  401.         mov     dword [exp_lfb+4], edx
  402.  
  403.         shr     edi, 12
  404.         mov     [pg_count], edi
  405.         shr     edi, 10
  406.  
  407.         bt      [cpu_caps], CAPS_PSE
  408.         jnc     .map_page_tables
  409.         or      esi, PG_LARGE+PG_UW
  410.         mov     edx, sys_proc+PROC.pdt_0+(LFB_BASE shr 20)
  411. @@:
  412.         mov     [edx], esi
  413.         add     edx, 4
  414.         add     esi, 0x00400000
  415.         dec     edi
  416.         jnz     @B
  417.  
  418.         bt      [cpu_caps], CAPS_PGE
  419.         jnc     @F
  420.         or      dword [sys_proc+PROC.pdt_0+(LFB_BASE shr 20)], PG_GLOBAL
  421. @@:
  422.         mov     dword [LFBAddress], LFB_BASE
  423.         mov     eax, cr3      ;flush TLB
  424.         mov     cr3, eax
  425.         ret
  426.  
  427. .map_page_tables:
  428.  
  429. @@:
  430.         call    alloc_page
  431.         stdcall map_page_table, edx, eax
  432.         add     edx, 0x00400000
  433.         dec     edi
  434.         jnz     @B
  435.  
  436.         mov     eax, [LFBAddress]
  437.         mov     edi, page_tabs + (LFB_BASE shr 10)
  438.         or      eax, PG_UW
  439.         mov     ecx, [pg_count]
  440.         cld
  441. @@:
  442.         stosd
  443.         add     eax, 0x1000
  444.         dec     ecx
  445.         jnz     @B
  446.  
  447.         mov     dword [LFBAddress], LFB_BASE
  448.         mov     eax, cr3      ;flush TLB
  449.         mov     cr3, eax
  450.  
  451.         ret
  452. endp
  453.  
  454. align 4
  455. proc new_mem_resize stdcall, new_size:dword
  456.  
  457.         push    ebx
  458.         push    esi
  459.         push    edi
  460.  
  461.         mov     edx, [current_slot]
  462.         mov     ebx, [edx+APPDATA.process]
  463.  
  464.         cmp     [ebx+PROC.heap_base], 0
  465.         jne     .exit
  466.  
  467.         mov     edi, [new_size]
  468.         add     edi, 4095
  469.         and     edi, not 4095
  470.         mov     [new_size], edi
  471.  
  472.         mov     esi, [ebx+PROC.mem_used]
  473.         add     esi, 4095
  474.         and     esi, not 4095
  475.  
  476.         cmp     edi, esi
  477.         ja      .expand
  478.         je      .exit
  479.  
  480.         mov     ebx, edi
  481.         shr     edi, 12
  482.         shr     esi, 12
  483.  
  484.         mov     ecx, pg_data.mutex
  485.         call    mutex_lock
  486. @@:
  487.         mov     eax, [app_page_tabs+edi*4]
  488.         test    eax, 1
  489.         jz      .next
  490.  
  491.         mov     dword [app_page_tabs+edi*4], 0
  492.         invlpg  [ebx]
  493.         call    free_page
  494.  
  495. .next:
  496.         inc     edi
  497.         add     ebx, 0x1000
  498.         cmp     edi, esi
  499.         jb      @B
  500.  
  501.         mov     ecx, pg_data.mutex
  502.         call    mutex_unlock
  503.  
  504. .update_size:
  505.         mov     edx, [current_slot]
  506.         mov     ebx, [new_size]
  507.         mov     edx, [edx+APPDATA.process]
  508.         mov     [edx+PROC.mem_used], ebx
  509. .exit:
  510.         pop     edi
  511.         pop     esi
  512.         pop     ebx
  513.         xor     eax, eax
  514.         ret
  515.  
  516. .expand:
  517.  
  518.         mov     ecx, pg_data.mutex
  519.         call    mutex_lock
  520.  
  521.         xchg    esi, edi
  522.  
  523.         push    esi                   ;new size
  524.         push    edi                   ;old size
  525.  
  526.         add     edi, 0x3FFFFF
  527.         and     edi, not(0x3FFFFF)
  528.         add     esi, 0x3FFFFF
  529.         and     esi, not(0x3FFFFF)
  530.  
  531.         cmp     edi, esi
  532.         jae     .grow
  533.  @@:
  534.         call    alloc_page
  535.         test    eax, eax
  536.         jz      .exit_fail
  537.  
  538.         stdcall map_page_table, edi, eax
  539.  
  540.         push    edi
  541.         shr     edi, 10
  542.         add     edi, page_tabs
  543.         mov     ecx, 1024
  544.         xor     eax, eax
  545.         cld
  546.         rep stosd
  547.         pop     edi
  548.  
  549.         add     edi, 0x00400000
  550.         cmp     edi, esi
  551.         jb      @B
  552. .grow:
  553.         pop     edi                   ;old size
  554.         pop     ecx                   ;new size
  555.  
  556.         shr     edi, 10
  557.         shr     ecx, 10
  558.         sub     ecx, edi
  559.         shr     ecx, 2                ;pages count
  560.         mov     eax, 2
  561.  
  562.         add     edi, app_page_tabs
  563.         rep stosd
  564.  
  565.         mov     ecx, pg_data.mutex
  566.         call    mutex_unlock
  567.  
  568.         jmp     .update_size
  569.  
  570. .exit_fail:
  571.         mov     ecx, pg_data.mutex
  572.         call    mutex_unlock
  573.  
  574.         add     esp, 8
  575.         pop     edi
  576.         pop     esi
  577.         pop     ebx
  578.         xor     eax, eax
  579.         inc     eax
  580.         ret
  581. endp
  582.  
  583.  
  584. ; param
  585. ;  eax= linear address
  586. ;
  587. ; retval
  588. ;  eax= phisical page address
  589.  
  590. align 4
  591. get_pg_addr:
  592.         sub     eax, OS_BASE
  593.         cmp     eax, 0x400000
  594.         jb      @f
  595.         shr     eax, 12
  596.         mov     eax, [page_tabs+(eax+(OS_BASE shr 12))*4]
  597. @@:
  598.         and     eax, 0xFFFFF000
  599.         ret
  600.  
  601.  
  602. align 4
  603. ; Now it is called from core/sys32::exc_c (see stack frame there)
  604. proc page_fault_handler
  605.  
  606.     .err_addr   equ ebp-4
  607.  
  608.         push    ebx               ;save exception number (#PF)
  609.         mov     ebp, esp
  610.         mov     ebx, cr2
  611.         push    ebx               ;that is locals: .err_addr = cr2
  612.         inc     [pg_data.pages_faults]
  613.  
  614.         mov     eax, [pf_err_code]
  615.  
  616.         cmp     ebx, OS_BASE      ;ebx == .err_addr
  617.         jb      .user_space       ;страница в памяти приложения ;
  618.  
  619.         cmp     ebx, page_tabs
  620.         jb      .kernel_space     ;страница в памяти ядра
  621.  
  622.         cmp     ebx, kernel_tabs
  623.         jb      .alloc;.app_tabs  ;таблицы страниц приложения ;
  624.                                   ;просто создадим одну
  625. if 0 ;пока это просто лишнее
  626.         cmp     ebx, LFB_BASE
  627.         jb      .core_tabs        ;таблицы страниц ядра
  628.                                   ;Ошибка
  629.   .lfb:
  630.                                   ;область LFB
  631.                                   ;Ошибка
  632.         jmp     .fail
  633. end if
  634. .core_tabs:
  635. .fail:  ;simply return to caller
  636.         mov     esp, ebp
  637.         pop     ebx               ;restore exception number (#PF)
  638.         ret
  639.  
  640. .user_space:
  641.         test    eax, PG_MAP
  642.         jnz     .err_access       ;Страница присутствует
  643.                                   ;Ошибка доступа ?
  644.  
  645.         shr     ebx, 12
  646.         mov     ecx, ebx
  647.         shr     ecx, 10
  648.         mov     edx, [master_tab+ecx*4]
  649.         test    edx, PG_MAP
  650.         jz      .fail             ;таблица страниц не создана
  651.                                   ;неверный адрес в программе
  652.  
  653.         mov     eax, [page_tabs+ebx*4]
  654.         test    eax, 2
  655.         jz      .fail             ;адрес не зарезервирован для ;
  656.                                   ;использования. Ошибка
  657. .alloc:
  658.         call    alloc_page
  659.         test    eax, eax
  660.         jz      .fail
  661.  
  662.         stdcall map_page, [.err_addr], eax, PG_UW
  663.  
  664.         mov     edi, [.err_addr]
  665.         and     edi, 0xFFFFF000
  666.         mov     ecx, 1024
  667.         xor     eax, eax
  668.        ;cld     ;caller is duty for this
  669.         rep stosd
  670. .exit:  ;iret with repeat fault instruction
  671.         add     esp, 12;clear in stack: locals(.err_addr) + #PF + ret_to_caller
  672.         restore_ring3_context
  673.         iretd
  674.  
  675. .err_access:
  676. ; access denied? this may be a result of copy-on-write protection for DLL
  677. ; check list of HDLLs
  678.         and     ebx, not 0xFFF
  679.         mov     eax, [current_process]
  680.         mov     eax, [eax+PROC.dlls_list_ptr]
  681.         test    eax, eax
  682.         jz      .fail
  683.         mov     esi, [eax+HDLL.fd]
  684. .scan_hdll:
  685.         cmp     esi, eax
  686.         jz      .fail
  687.         mov     edx, ebx
  688.         sub     edx, [esi+HDLL.base]
  689.         cmp     edx, [esi+HDLL.size]
  690.         jb      .fault_in_hdll
  691. .scan_hdll.next:
  692.         mov     esi, [esi+HDLL.fd]
  693.         jmp     .scan_hdll
  694. .fault_in_hdll:
  695. ; allocate new page, map it as rw and copy data
  696.         call    alloc_page
  697.         test    eax, eax
  698.         jz      .fail
  699.         stdcall map_page, ebx, eax, PG_UW
  700.         mov     edi, ebx
  701.         mov     ecx, 1024
  702.         sub     ebx, [esi+HDLL.base]
  703.         mov     esi, [esi+HDLL.parent]
  704.         mov     esi, [esi+DLLDESCR.data]
  705.         add     esi, ebx
  706.         rep movsd
  707.         jmp     .exit
  708.  
  709. .kernel_space:
  710.         test    eax, PG_MAP
  711.         jz      .fail   ;страница не присутствует
  712.  
  713.         test    eax, 12 ;U/S (+below)
  714.         jnz     .fail   ;приложение обратилось к памяти
  715.                         ;ядра
  716.        ;test    eax, 8
  717.        ;jnz     .fail   ;установлен зарезервированный бит
  718.                         ;в таблицах страниц. добавлено в P4/Xeon
  719.  
  720. ;попытка записи в защищённую страницу ядра
  721.  
  722.         cmp     ebx, tss._io_map_0
  723.         jb      .fail
  724.  
  725.         cmp     ebx, tss._io_map_0+8192
  726.         jae     .fail
  727.  
  728. ; io permission map
  729. ; copy-on-write protection
  730.  
  731.         call    alloc_page
  732.         test    eax, eax
  733.         jz      .fail
  734.  
  735.         push    eax
  736.         stdcall map_page, [.err_addr], eax, dword PG_SW
  737.         pop     eax
  738.         mov     edi, [.err_addr]
  739.         and     edi, -4096
  740.         lea     esi, [edi+(not tss._io_map_0)+1]; -tss._io_map_0
  741.  
  742.         mov     ebx, esi
  743.         shr     ebx, 12
  744.         mov     edx, [current_slot]
  745.         or      eax, PG_SW
  746.         mov     [edx+APPDATA.io_map+ebx*4], eax
  747.  
  748.         add     esi, [default_io_map]
  749.         mov     ecx, 4096/4
  750.        ;cld     ;caller is duty for this
  751.         rep movsd
  752.         jmp     .exit
  753. endp
  754.  
  755. ; returns number of mapped bytes
  756. proc map_mem_ipc stdcall, lin_addr:dword,slot:dword,\
  757.                       ofs:dword,buf_size:dword,req_access:dword
  758.         locals
  759.              count   dd ?
  760.              process dd ?
  761.         endl
  762.  
  763.         mov     [count], 0
  764.         cmp     [buf_size], 0
  765.         jz      .exit
  766.  
  767.         mov     eax, [slot]
  768.         shl     eax, 8
  769.         mov     eax, [SLOT_BASE+eax+APPDATA.process]
  770.         test    eax, eax
  771.         jz      .exit
  772.  
  773.         mov     [process], eax
  774.         mov     ebx, [ofs]
  775.         shr     ebx, 22
  776.         mov     eax, [eax+PROC.pdt_0+ebx*4]                 ;get page table
  777.         mov     esi, [ipc_ptab]
  778.         and     eax, 0xFFFFF000
  779.         jz      .exit
  780.         stdcall map_page, esi, eax, PG_SW
  781. @@:
  782.         mov     edi, [lin_addr]
  783.         and     edi, 0xFFFFF000
  784.         mov     ecx, [buf_size]
  785.         add     ecx, 4095
  786.         shr     ecx, 12
  787.         inc     ecx                  ; ???????????
  788.  
  789.         mov     edx, [ofs]
  790.         shr     edx, 12
  791.         and     edx, 0x3FF
  792. .map:
  793.         stdcall safe_map_page, [slot], [req_access], [ofs]
  794.         jnc     .exit
  795.         add     dword [ebp-4], PAGE_SIZE
  796.         add     [ofs], PAGE_SIZE
  797.         dec     ecx
  798.         jz      .exit
  799.  
  800.         add     edi, PAGE_SIZE
  801.         inc     edx
  802.         cmp     edx, 1024
  803.         jnz     .map
  804.  
  805.         inc     ebx
  806.         mov     eax, [process]
  807.         mov     eax, [eax+PROC.pdt_0+ebx*4]
  808.         and     eax, 0xFFFFF000
  809.         jz      .exit
  810.  
  811.         stdcall map_page, esi, eax, PG_SW
  812.         xor     edx, edx
  813.         jmp     .map
  814.  
  815. .exit:
  816.         pop     eax
  817.         ret
  818. endp
  819.  
  820. proc map_memEx stdcall, lin_addr:dword,slot:dword,\
  821.                         ofs:dword,buf_size:dword,req_access:dword
  822.         push    0 ; initialize number of mapped bytes
  823.  
  824.         cmp     [buf_size], 0
  825.         jz      .exit
  826.  
  827.         mov     eax, [slot]
  828.         shl     eax, 8
  829.         mov     eax, [SLOT_BASE+eax+APPDATA.process]
  830.         mov     eax, [eax+PROC.pdt_0_phys]
  831.         and     eax, 0xFFFFF000
  832.  
  833.         stdcall map_page, [proc_mem_pdir], eax, PG_UW
  834.         mov     ebx, [ofs]
  835.         shr     ebx, 22
  836.         mov     esi, [proc_mem_pdir]
  837.         mov     edi, [proc_mem_tab]
  838.         mov     eax, [esi+ebx*4]
  839.         and     eax, 0xFFFFF000
  840.         test    eax, eax
  841.         jz      .exit
  842.         stdcall map_page, edi, eax, PG_UW
  843.  
  844. @@:
  845.         mov     edi, [lin_addr]
  846.         and     edi, 0xFFFFF000
  847.         mov     ecx, [buf_size]
  848.         add     ecx, 4095
  849.         shr     ecx, 12
  850.         inc     ecx
  851.  
  852.         mov     edx, [ofs]
  853.         shr     edx, 12
  854.         and     edx, 0x3FF
  855.         mov     esi, [proc_mem_tab]
  856.  
  857. .map:
  858.         stdcall safe_map_page, [slot], [req_access], [ofs]
  859.         jnc     .exit
  860.         add     dword [ebp-4], 0x1000
  861.         add     edi, 0x1000
  862.         add     [ofs], 0x1000
  863.         inc     edx
  864.         dec     ecx
  865.         jnz     .map
  866. .exit:
  867.         pop     eax
  868.         ret
  869. endp
  870.  
  871. ; in: esi+edx*4 = pointer to page table entry
  872. ; in: [slot], [req_access], [ofs] on the stack
  873. ; in: edi = linear address to map
  874. ; out: CF cleared <=> failed
  875. ; destroys: only eax
  876. proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword
  877.         mov     eax, [esi+edx*4]
  878.         test    al, PG_MAP
  879.         jz      .not_present
  880.         test    al, PG_WRITE
  881.         jz      .resolve_readonly
  882. ; normal case: writable page, just map with requested access
  883. .map:
  884.         stdcall map_page, edi, eax, [req_access]
  885.         stc
  886. .fail:
  887.         ret
  888. .not_present:
  889. ; check for alloc-on-demand page
  890.         test    al, 2
  891.         jz      .fail
  892. ; allocate new page, save it to source page table
  893.         push    ecx
  894.         call    alloc_page
  895.         pop     ecx
  896.         test    eax, eax
  897.         jz      .fail
  898.         or      al, PG_UW
  899.         mov     [esi+edx*4], eax
  900.         jmp     .map
  901. .resolve_readonly:
  902. ; readonly page, probably copy-on-write
  903. ; check: readonly request of readonly page is ok
  904.         test    [req_access], PG_WRITE
  905.         jz      .map
  906. ; find control structure for this page
  907.         pushf
  908.         cli
  909.         cld
  910.         push    ebx ecx
  911.         mov     eax, [slot]
  912.         shl     eax, 8
  913.         mov     eax, [SLOT_BASE+eax+APPDATA.process]
  914.         mov     eax, [eax+PROC.dlls_list_ptr]
  915.         test    eax, eax
  916.         jz      .no_hdll
  917.         mov     ecx, [eax+HDLL.fd]
  918. .scan_hdll:
  919.         cmp     ecx, eax
  920.         jz      .no_hdll
  921.         mov     ebx, [ofs]
  922.         and     ebx, not 0xFFF
  923.         sub     ebx, [ecx+HDLL.base]
  924.         cmp     ebx, [ecx+HDLL.size]
  925.         jb      .hdll_found
  926.         mov     ecx, [ecx+HDLL.fd]
  927.         jmp     .scan_hdll
  928. .no_hdll:
  929.         pop     ecx ebx
  930.         popf
  931.         clc
  932.         ret
  933. .hdll_found:
  934. ; allocate page, save it in page table, map it, copy contents from base
  935.         mov     eax, [ecx+HDLL.parent]
  936.         add     ebx, [eax+DLLDESCR.data]
  937.         call    alloc_page
  938.         test    eax, eax
  939.         jz      .no_hdll
  940.         or      al, PG_UW
  941.         mov     [esi+edx*4], eax
  942.         stdcall map_page, edi, eax, [req_access]
  943.         push    esi edi
  944.         mov     esi, ebx
  945.         mov     ecx, 4096/4
  946.         rep movsd
  947.         pop     edi esi
  948.         pop     ecx ebx
  949.         popf
  950.         stc
  951.         ret
  952. endp
  953.  
  954. sys_IPC:
  955. ;input:
  956. ;  ebx=1 - set ipc buffer area
  957. ;    ecx=address of buffer
  958. ;    edx=size of buffer
  959. ;  eax=2 - send message
  960. ;    ebx=PID
  961. ;    ecx=address of message
  962. ;    edx=size of message
  963.  
  964.         dec     ebx
  965.         jnz     @f
  966.  
  967.         mov     eax, [current_slot]
  968.         pushf
  969.         cli
  970.         mov     [eax+APPDATA.ipc_start], ecx    ;set fields in extended information area
  971.         mov     [eax+APPDATA.ipc_size], edx
  972.  
  973.         add     edx, ecx
  974.         add     edx, 4095
  975.         and     edx, not 4095
  976.  
  977. .touch:
  978.         mov     eax, [ecx]
  979.         add     ecx, 0x1000
  980.         cmp     ecx, edx
  981.         jb      .touch
  982.  
  983.         popf
  984.         mov     [esp+32], ebx   ;ebx=0
  985.         ret
  986.  
  987. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  988. ;2
  989. @@:
  990.         dec     ebx
  991.         jnz     @f
  992.  
  993.         stdcall sys_ipc_send, ecx, edx, esi
  994.         mov     [esp+32], eax
  995.         ret
  996. @@:
  997.         or      eax, -1
  998.         mov     [esp+32], eax
  999.         ret
  1000.  
  1001. proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
  1002.            locals
  1003.              dst_slot   dd ?
  1004.              dst_offset dd ?
  1005.              buf_size   dd ?
  1006.              used_buf   dd ?
  1007.            endl
  1008.  
  1009.         pushf
  1010.         cli
  1011.  
  1012.         mov     eax, [PID]
  1013.         call    pid_to_slot
  1014.         test    eax, eax
  1015.         jz      .no_pid
  1016.  
  1017.         mov     [dst_slot], eax
  1018.         shl     eax, 8
  1019.         mov     edi, [eax+SLOT_BASE+APPDATA.ipc_start] ;is ipc area defined?
  1020.         test    edi, edi
  1021.         jz      .no_ipc_area
  1022.  
  1023.         mov     ebx, edi
  1024.         and     ebx, 0xFFF
  1025.         mov     [dst_offset], ebx
  1026.  
  1027.         mov     esi, [eax+SLOT_BASE+APPDATA.ipc_size]
  1028.         mov     [buf_size], esi
  1029.  
  1030.         mov     ecx, [ipc_tmp]
  1031.         cmp     esi, 0x40000-0x1000; size of [ipc_tmp] minus one page
  1032.         jbe     @f
  1033.         push    esi edi
  1034.         add     esi, 0x1000
  1035.         stdcall alloc_kernel_space, esi
  1036.         mov     ecx, eax
  1037.         pop     edi esi
  1038. @@:
  1039.         mov     [used_buf], ecx
  1040.         stdcall map_mem_ipc, ecx, [dst_slot], \
  1041.                 edi, esi, PG_SW
  1042.  
  1043.         mov     edi, [dst_offset]
  1044.         add     edi, [used_buf]
  1045.         cmp     dword [edi], 0
  1046.         jnz     .ipc_blocked          ;if dword [buffer]<>0 - ipc blocked now
  1047.  
  1048.         mov     edx, dword [edi+4]
  1049.         lea     ebx, [edx+8]
  1050.         add     ebx, [msg_size]
  1051.         cmp     ebx, [buf_size]
  1052.         ja      .buffer_overflow       ;esi<0 - not enough memory in buffer
  1053.  
  1054.         mov     dword [edi+4], ebx
  1055.         mov     eax, [TASK_BASE]
  1056.         mov     eax, [eax+0x04]        ;eax - our PID
  1057.         add     edi, edx
  1058.         mov     [edi], eax
  1059.         mov     ecx, [msg_size]
  1060.  
  1061.         mov     [edi+4], ecx
  1062.         add     edi, 8
  1063.         mov     esi, [msg_addr]
  1064.        ;    add esi, new_app_base
  1065.         cld
  1066.         rep movsb
  1067.  
  1068.         mov     ebx, [ipc_tmp]
  1069.         mov     edx, ebx
  1070.         shr     ebx, 12
  1071.         xor     eax, eax
  1072.         mov     [page_tabs+ebx*4], eax
  1073.         invlpg  [edx]
  1074.  
  1075.         mov     ebx, [ipc_pdir]
  1076.         mov     edx, ebx
  1077.         shr     ebx, 12
  1078.         xor     eax, eax
  1079.         mov     [page_tabs+ebx*4], eax
  1080.         invlpg  [edx]
  1081.  
  1082.         mov     ebx, [ipc_ptab]
  1083.         mov     edx, ebx
  1084.         shr     ebx, 12
  1085.         xor     eax, eax
  1086.         mov     [page_tabs+ebx*4], eax
  1087.         invlpg  [edx]
  1088.  
  1089.         mov     eax, [dst_slot]
  1090.         shl     eax, 8
  1091.         or      [eax+SLOT_BASE+0xA8], dword 0x40
  1092.         push    0
  1093.         jmp     .ret
  1094. .no_pid:
  1095.         popf
  1096.         mov     eax, 4
  1097.         ret
  1098. .no_ipc_area:
  1099.         popf
  1100.         xor     eax, eax
  1101.         inc     eax
  1102.         ret
  1103. .ipc_blocked:
  1104.         push    2
  1105.         jmp     .ret
  1106. .buffer_overflow:
  1107.         push    3
  1108. .ret:
  1109.         mov     eax, [used_buf]
  1110.         cmp     eax, [ipc_tmp]
  1111.         je      @f
  1112.         stdcall free_kernel_space, eax
  1113. @@:
  1114.         pop     eax
  1115.         popf
  1116.         ret
  1117. endp
  1118.  
  1119. align 4
  1120. sysfn_meminfo:
  1121.  
  1122.         ;   add ecx, new_app_base
  1123.         cmp     ecx, OS_BASE
  1124.         jae     .fail
  1125.  
  1126.         mov     eax, [pg_data.pages_count]
  1127.         mov     [ecx], eax
  1128.         shl     eax, 12
  1129.         mov     [esp+32], eax
  1130.         mov     eax, [pg_data.pages_free]
  1131.         mov     [ecx+4], eax
  1132.         mov     eax, [pg_data.pages_faults]
  1133.         mov     [ecx+8], eax
  1134.         mov     eax, [heap_size]
  1135.         mov     [ecx+12], eax
  1136.         mov     eax, [heap_free]
  1137.         mov     [ecx+16], eax
  1138.         mov     eax, [heap_blocks]
  1139.         mov     [ecx+20], eax
  1140.         mov     eax, [free_blocks]
  1141.         mov     [ecx+24], eax
  1142.         ret
  1143. .fail:
  1144.         or      dword [esp+32], -1
  1145.         ret
  1146.  
  1147. align 4
  1148. f68:
  1149.         cmp     ebx, 4
  1150.         jbe     sys_sheduler
  1151.  
  1152.         cmp     ebx, 11
  1153.         jb      .fail
  1154.  
  1155.         cmp     ebx, 27
  1156.         ja      .fail
  1157.  
  1158.         jmp     dword [f68call+ebx*4-11*4]
  1159. .11:
  1160.         call    init_heap
  1161.         mov     [esp+32], eax
  1162.         ret
  1163. .12:
  1164.         stdcall user_alloc, ecx
  1165.         mov     [esp+32], eax
  1166.         ret
  1167. .13:
  1168.         stdcall user_free, ecx
  1169.         mov     [esp+32], eax
  1170.         ret
  1171. .14:
  1172.         cmp     ecx, OS_BASE
  1173.         jae     .fail
  1174.         mov     edi, ecx
  1175.         call    get_event_ex
  1176.         mov     [esp+32], eax
  1177.         ret
  1178. .16:
  1179.         test    ecx, ecx
  1180.         jz      .fail
  1181.         cmp     ecx, OS_BASE
  1182.         jae     .fail
  1183.         stdcall get_service, ecx
  1184.         mov     [esp+32], eax
  1185.         ret
  1186. .17:
  1187.         call    srv_handlerEx   ;ecx
  1188.         mov     [esp+32], eax
  1189.         ret
  1190. .19:
  1191.         cmp     ecx, OS_BASE
  1192.         jae     .fail
  1193.         stdcall load_library, ecx
  1194.         mov     [esp+32], eax
  1195.         ret
  1196. .20:
  1197.         mov     eax, edx
  1198.         mov     ebx, ecx
  1199.         call    user_realloc            ;in: eax = pointer, ebx = new size
  1200.         mov     [esp+32], eax
  1201.         ret
  1202. .21:
  1203.         cmp     ecx, OS_BASE
  1204.         jae     .fail
  1205.  
  1206.         cmp     edx, OS_BASE
  1207.         jae     .fail
  1208.  
  1209.         stdcall load_pe_driver, ecx, edx
  1210.         mov     [esp+32], eax
  1211.         ret
  1212. .22:
  1213.         cmp     ecx, OS_BASE
  1214.         jae     .fail
  1215.  
  1216.         stdcall shmem_open, ecx, edx, esi
  1217.         mov     [esp+24], edx
  1218.         mov     [esp+32], eax
  1219.         ret
  1220.  
  1221. .23:
  1222.         cmp     ecx, OS_BASE
  1223.         jae     .fail
  1224.  
  1225.         stdcall shmem_close, ecx
  1226.         mov     [esp+32], eax
  1227.         ret
  1228. .24:
  1229.         mov     eax, [current_slot]
  1230.         xchg    ecx, [eax+APPDATA.exc_handler]
  1231.         xchg    edx, [eax+APPDATA.except_mask]
  1232.         mov     [esp+32], ecx ; reg_eax+8
  1233.         mov     [esp+20], edx ; reg_ebx+8
  1234.         ret
  1235. .25:
  1236.         cmp     ecx, 32
  1237.         jae     .fail
  1238.         mov     eax, [current_slot]
  1239.         btr     [eax+APPDATA.except_mask], ecx
  1240.         setc    byte[esp+32]
  1241.         jecxz   @f
  1242.         bts     [eax+APPDATA.except_mask], ecx
  1243. @@:
  1244.         ret
  1245.  
  1246. .26:
  1247.         stdcall user_unmap, ecx, edx, esi
  1248.         mov     [esp+32], eax
  1249.         ret
  1250.  
  1251. .27:
  1252.         cmp     ecx, OS_BASE
  1253.         jae     .fail
  1254.  
  1255.         stdcall load_file_umode, ecx
  1256.         mov     [esp+24], edx
  1257.         mov     [esp+32], eax
  1258.         ret
  1259.  
  1260. .fail:
  1261.         xor     eax, eax
  1262.         mov     [esp+32], eax
  1263.         ret
  1264.  
  1265.  
  1266. align 4
  1267. f68call:   ; keep this table closer to main code
  1268.  
  1269.            dd f68.11   ; init_heap
  1270.            dd f68.12   ; user_alloc
  1271.            dd f68.13   ; user_free
  1272.            dd f68.14   ; get_event_ex
  1273.            dd f68.fail ; moved to f68.24
  1274.            dd f68.16   ; get_service
  1275.            dd f68.17   ; call_service
  1276.            dd f68.fail ; moved to f68.25
  1277.            dd f68.19   ; load_dll
  1278.            dd f68.20   ; user_realloc
  1279.            dd f68.21   ; load_driver
  1280.            dd f68.22   ; shmem_open
  1281.            dd f68.23   ; shmem_close
  1282.            dd f68.24   ; set exception handler
  1283.            dd f68.25   ; unmask exception
  1284.            dd f68.26   ; user_unmap
  1285.            dd f68.27   ; load_file_umode
  1286.  
  1287.  
  1288. align 4
  1289. proc load_pe_driver stdcall, file:dword, cmdline:dword
  1290.         push    esi
  1291.  
  1292.         stdcall load_PE, [file]
  1293.         test    eax, eax
  1294.         jz      .fail
  1295.  
  1296.         mov     esi, eax
  1297.         push    [cmdline]
  1298.         push    DRV_ENTRY
  1299.         call    eax
  1300.         pop     ecx
  1301.         pop     ecx
  1302.         test    eax, eax
  1303.         jz      .fail
  1304.  
  1305.         mov     [eax+SRV.entry], esi
  1306.         pop     esi
  1307.         ret
  1308.  
  1309. .fail:
  1310.         xor     eax, eax
  1311.         pop     esi
  1312.         ret
  1313. endp
  1314.  
  1315. align 4
  1316. proc init_mtrr
  1317.  
  1318.         cmp     [BOOT_VARS+BOOT_MTRR], byte 2
  1319.         je      .exit
  1320.  
  1321.         bt      [cpu_caps], CAPS_MTRR
  1322.         jnc     .exit
  1323.  
  1324.         mov     eax, cr0
  1325.         or      eax, 0x60000000 ;disable caching
  1326.         mov     cr0, eax
  1327.         wbinvd                  ;invalidate cache
  1328.  
  1329.         mov     ecx, 0x2FF
  1330.         rdmsr                   ;
  1331. ; has BIOS already initialized MTRRs?
  1332.         test    ah, 8
  1333.         jnz     .skip_init
  1334. ; rarely needed, so mainly placeholder
  1335. ; main memory - cached
  1336.         push    eax
  1337.  
  1338.         mov     eax, [MEM_AMOUNT]
  1339. ; round eax up to next power of 2
  1340.         dec     eax
  1341.         bsr     ecx, eax
  1342.         mov     ebx, 2
  1343.         shl     ebx, cl
  1344.         dec     ebx
  1345. ; base of memory range = 0, type of memory range = MEM_WB
  1346.         xor     edx, edx
  1347.         mov     eax, MEM_WB
  1348.         mov     ecx, 0x200
  1349.         wrmsr
  1350. ; mask of memory range = 0xFFFFFFFFF - (size - 1), ebx = size - 1
  1351.         mov     eax, 0xFFFFFFFF
  1352.         mov     edx, 0x0000000F
  1353.         sub     eax, ebx
  1354.         sbb     edx, 0
  1355.         or      eax, 0x800
  1356.         inc     ecx
  1357.         wrmsr
  1358. ; clear unused MTRRs
  1359.         xor     eax, eax
  1360.         xor     edx, edx
  1361. @@:
  1362.         inc     ecx
  1363.         wrmsr
  1364.         cmp     ecx, 0x20F
  1365.         jb      @b
  1366. ; enable MTRRs
  1367.         pop     eax
  1368.         or      ah, 8
  1369.         and     al, 0xF0; default memtype = UC
  1370.         mov     ecx, 0x2FF
  1371.         wrmsr
  1372. .skip_init:
  1373.         stdcall set_mtrr, [LFBAddress], [LFBSize], MEM_WC
  1374.  
  1375.         wbinvd                  ;again invalidate
  1376.  
  1377.         mov     eax, cr0
  1378.         and     eax, not 0x60000000
  1379.         mov     cr0, eax        ; enable caching
  1380. .exit:
  1381.         ret
  1382. endp
  1383.  
  1384. align 4
  1385. proc set_mtrr stdcall, base:dword,size:dword,mem_type:dword
  1386. ; find unused register
  1387.         mov     ecx, 0x201
  1388. @@:
  1389.         rdmsr
  1390.         dec     ecx
  1391.         test    ah, 8
  1392.         jz      .found
  1393.         rdmsr
  1394.         mov     al, 0; clear memory type field
  1395.         cmp     eax, [base]
  1396.         jz      .ret
  1397.         add     ecx, 3
  1398.         cmp     ecx, 0x210
  1399.         jb      @b
  1400. ; no free registers, ignore the call
  1401. .ret:
  1402.         ret
  1403. .found:
  1404. ; found, write values
  1405.         xor     edx, edx
  1406.         mov     eax, [base]
  1407.         or      eax, [mem_type]
  1408.         wrmsr
  1409.  
  1410.         mov     ebx, [size]
  1411.         dec     ebx
  1412.         mov     eax, 0xFFFFFFFF
  1413.         mov     edx, 0x00000000
  1414.         sub     eax, ebx
  1415.         sbb     edx, 0
  1416.         or      eax, 0x800
  1417.         inc     ecx
  1418.         wrmsr
  1419.         ret
  1420. endp
  1421.  
  1422. align 4
  1423. proc create_ring_buffer stdcall, size:dword, flags:dword
  1424.            locals
  1425.              buf_ptr  dd ?
  1426.            endl
  1427.  
  1428.         mov     eax, [size]
  1429.         test    eax, eax
  1430.         jz      .fail
  1431.  
  1432.         add     eax, eax
  1433.         stdcall alloc_kernel_space, eax
  1434.         test    eax, eax
  1435.         jz      .fail
  1436.  
  1437.         push    ebx
  1438.  
  1439.         mov     [buf_ptr], eax
  1440.  
  1441.         mov     ebx, [size]
  1442.         shr     ebx, 12
  1443.         push    ebx
  1444.  
  1445.         stdcall alloc_pages, ebx
  1446.         pop     ecx
  1447.  
  1448.         test    eax, eax
  1449.         jz      .mm_fail
  1450.  
  1451.         push    edi
  1452.  
  1453.         or      eax, [flags]
  1454.         mov     edi, [buf_ptr]
  1455.         mov     ebx, [buf_ptr]
  1456.         mov     edx, ecx
  1457.         shl     edx, 2
  1458.         shr     edi, 10
  1459. @@:
  1460.         mov     [page_tabs+edi], eax
  1461.         mov     [page_tabs+edi+edx], eax
  1462.         invlpg  [ebx]
  1463.         invlpg  [ebx+0x10000]
  1464.         add     eax, 0x1000
  1465.         add     ebx, 0x1000
  1466.         add     edi, 4
  1467.         dec     ecx
  1468.         jnz     @B
  1469.  
  1470.         mov     eax, [buf_ptr]
  1471.         pop     edi
  1472.         pop     ebx
  1473.         ret
  1474. .mm_fail:
  1475.         stdcall free_kernel_space, [buf_ptr]
  1476.         xor     eax, eax
  1477.         pop     ebx
  1478. .fail:
  1479.         ret
  1480. endp
  1481.  
  1482.  
  1483. align 4
  1484. proc print_mem
  1485.         mov     edi, BOOT_VAR + 0x9104
  1486.         mov     ecx, [edi-4]
  1487.         test    ecx, ecx
  1488.         jz      .done
  1489.  
  1490. @@:
  1491.         mov     eax, [edi]
  1492.         mov     edx, [edi+4]
  1493.         add     eax, [edi+8]
  1494.         adc     edx, [edi+12]
  1495.  
  1496.         DEBUGF  1, "K : E820 %x%x - %x%x type %d\n", \
  1497.                     [edi+4], [edi],\
  1498.                     edx, eax, [edi+16]
  1499.         add     edi, 20
  1500.         dec     ecx
  1501.         jnz     @b
  1502. .done:
  1503.         ret
  1504. endp
  1505.