Subversion Repositories Kolibri OS

Rev

Rev 425 | Rev 448 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. $Revision: 431 $
  2. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3. ;;                                                              ;;
  4. ;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
  5. ;; Distributed under terms of the GNU General Public License    ;;
  6. ;;                                                              ;;
  7. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  8.  
  9. tmp_page_tab      equ HEAP_BASE
  10.  
  11. align 4
  12. proc mem_test
  13.  
  14.            mov eax, cr0
  15.            and eax, not (CR0_CD+CR0_NW)
  16.            or eax, CR0_CD         ;disable caching
  17.            mov cr0, eax
  18.            wbinvd                 ;invalidate cache
  19.  
  20.            xor edi, edi
  21.            mov ebx, 'TEST'
  22. @@:
  23.            add edi, 0x400000
  24.            xchg ebx, dword [edi]
  25.            cmp dword [edi], 'TEST'
  26.            xchg ebx, dword [edi]
  27.            je @b
  28.            mov [MEM_AMOUNT], edi
  29.  
  30.            and eax, not (CR0_CD+CR0_NW)  ;enable caching
  31.            mov cr0, eax
  32.            mov eax, edi
  33.            mov [LFBSize], 0x00800000
  34.            ret
  35. endp
  36.  
  37. align 4
  38. proc init_mem
  39.  
  40.            mov eax, [MEM_AMOUNT]
  41.  
  42.            mov [pg_data.mem_amount], eax
  43.            mov [pg_data.kernel_max], eax
  44.  
  45.            shr eax, 12
  46.            mov edx, eax
  47.            mov [pg_data.pages_count], eax
  48.            mov [pg_data.kernel_pages], eax
  49.  
  50.            shr eax, 3
  51.            mov [pg_data.pagemap_size], eax
  52.  
  53.            shr edx, 10
  54.            cmp edx, 3
  55.            ja @f
  56.            inc edx       ;at least 4Mb for kernel heap
  57. @@:
  58.            mov [pg_data.kernel_tables], edx
  59.  
  60.            xor eax, eax
  61.            mov edi, sys_pgdir
  62.            mov ecx, 2048
  63.            cld
  64.            rep stosd
  65.  
  66.            mov edx, sys_pgdir
  67.            bt [cpu_caps], CAPS_PSE
  68.            jnc .no_PSE
  69.  
  70.            mov ebx, cr4
  71.            or ebx, CR4_PSE
  72.            mov eax, PG_LARGE+PG_SW
  73.            bt [cpu_caps], CAPS_PGE
  74.            jnc @F
  75.            or eax, PG_GLOBAL
  76.            or ebx, CR4_PGE
  77. @@:
  78.            mov cr4, ebx
  79.            sub [pg_data.kernel_tables], 2
  80.  
  81.            mov [edx], eax
  82.            add eax, 0x00400000
  83.            mov [edx+4], eax
  84.            add edx, 8
  85.  
  86.            mov eax, 0x800000+PG_SW
  87.            mov ecx, (HEAP_BASE-0x800000)/4096
  88.            jmp .map_low
  89. .no_PSE:
  90.            mov eax, PG_SW
  91.            mov ecx, HEAP_BASE/4096
  92. .map_low:
  93.            mov edi, tmp_page_tab
  94. @@:                                   ;
  95.            stosd
  96.            add eax, 0x1000
  97.            dec ecx
  98.            jnz @B
  99.  
  100.            mov ecx, [pg_data.kernel_tables]
  101.            shl ecx, 10
  102.            xor eax, eax
  103.            rep stosd
  104.  
  105.            mov ecx, [pg_data.kernel_tables]
  106.            mov eax, tmp_page_tab+PG_SW
  107.            mov edi, edx
  108.  
  109. .map_kernel_tabs:
  110.  
  111.            stosd
  112.            add eax, 0x1000
  113.            dec ecx
  114.            jnz .map_kernel_tabs
  115.  
  116.            mov dword [sys_pgdir+(page_tabs shr 20)], sys_pgdir+PG_SW
  117.            ret
  118. endp
  119.  
  120. align 4
  121. proc init_page_map
  122.  
  123.            mov edi, sys_pgmap
  124.            mov ecx, (HEAP_BASE/4096)/32      ;384/4
  125.            mov ebx, ecx
  126.            xor eax,eax
  127.            cld
  128.            rep stosd
  129.  
  130.            not eax
  131.            mov ecx, [pg_data.pagemap_size]
  132.            sub ecx, ebx
  133.            shr ecx, 2
  134.            rep stosd
  135.  
  136.            lea edi, [sys_pgmap+ebx*4]         ;+384
  137.            mov edx, [pg_data.pages_count]
  138.            mov ecx, [pg_data.kernel_tables]
  139.            add ecx, (HEAP_BASE/4096) and 31
  140.            sub edx, HEAP_BASE/4096
  141.            sub edx, ecx
  142.            mov [pg_data.pages_free], edx
  143.  
  144.            xor eax, eax
  145.            mov ebx, ecx
  146.            shr ecx, 5
  147.            rep stosd
  148.  
  149.            not eax
  150.            mov ecx, ebx
  151.            and ecx, 31
  152.            shl eax, cl
  153.            mov [page_start], edi;           sys_pgmap+384
  154.            stosd
  155.  
  156.            mov ebx, sys_pgmap
  157.            add ebx, [pg_data.pagemap_size]
  158.            mov [page_end], ebx
  159.  
  160.            mov [pg_data.pg_mutex], 0
  161.  
  162.            ret
  163. endp
  164.  
  165. align 4
  166. proc alloc_page
  167.  
  168.            pushfd
  169.            cli
  170.            mov ebx, [page_start]
  171.            mov ecx, [page_end]
  172. .l1:
  173.            bsf eax,[ebx];
  174.            jnz .found
  175.            add ebx,4
  176.            cmp ebx, ecx
  177.            jb .l1
  178.            popfd
  179.            xor eax,eax
  180.            ret
  181. .found:
  182.            btr [ebx], eax
  183.            mov [page_start],ebx
  184.            sub ebx, sys_pgmap
  185.            lea eax, [eax+ebx*8]
  186.            shl eax, 12
  187.            dec [pg_data.pages_free]
  188.            popfd
  189.            ret
  190. endp
  191.  
  192. align 4
  193. proc alloc_pages stdcall, count:dword
  194.            pushfd
  195.            cli
  196.            mov eax, [count]
  197.            add eax, 7
  198.            shr eax, 3
  199.            mov [count], eax
  200.            cmp eax, [pg_data.pages_free]
  201.            ja .fail
  202.  
  203.            mov ecx, [page_start]
  204.            mov ebx, [page_end]
  205. .find:
  206.            mov edx, [count]
  207.            mov edi, ecx
  208. .match:
  209.            cmp byte [ecx], 0xFF
  210.            jne .next
  211.            dec edx
  212.            jz .ok
  213.            inc ecx
  214.            cmp ecx,ebx
  215.            jb .match
  216. .fail:     xor eax, eax
  217.            popfd
  218.            ret
  219. .next:
  220.            inc ecx
  221.            cmp ecx, ebx
  222.            jb .find
  223.            popfd
  224.            xor eax, eax
  225.            ret
  226. .ok:
  227.            sub ecx, edi
  228.            inc ecx
  229.            mov esi, edi
  230.            xor eax, eax
  231.            rep stosb
  232.            sub esi, sys_pgmap
  233.            shl esi, 3+12
  234.            mov eax, esi
  235.            mov ebx, [count]
  236.            shl ebx, 3
  237.            sub [pg_data.pages_free], ebx
  238.            popfd
  239.            ret
  240. endp
  241.  
  242. align 4
  243. proc map_page stdcall,lin_addr:dword,phis_addr:dword,flags:dword
  244.            push ebx
  245.            mov eax, [phis_addr]
  246.            and eax, not 0xFFF
  247.            or eax, [flags]
  248.            mov ebx, [lin_addr]
  249.            shr ebx, 12
  250.            mov [page_tabs+ebx*4], eax
  251.            mov eax, [lin_addr]
  252.            invlpg [eax]
  253.            pop ebx
  254.            ret
  255. endp
  256.  
  257. align 4
  258. map_space:    ;not implemented
  259.  
  260.  
  261.            ret
  262.  
  263.  
  264. align 4
  265. proc free_page
  266. ;arg:  eax  page address
  267.            pushfd
  268.            cli
  269.            shr eax, 12              ;page index
  270.            mov ebx, sys_pgmap
  271.            bts [ebx], eax           ;that's all!
  272.            cmc
  273.            adc [pg_data.pages_free], 0
  274.            shr eax, 3
  275.            and eax, not 3           ;dword offset from page_map
  276.            add eax, ebx
  277.            cmp [page_start], eax
  278.            ja @f
  279.            popfd
  280.            ret
  281. @@:
  282.            mov [page_start], eax
  283.            popfd
  284.            ret
  285. endp
  286.  
  287. ; param
  288. ;  eax= page base + page flags
  289. ;  ebx= liear address
  290. ;  ecx= count
  291.  
  292. align 4
  293. commit_pages:
  294.  
  295.            test ecx, ecx
  296.            jz .fail
  297.  
  298.            mov edi, ebx
  299.            mov ebx, pg_data.pg_mutex
  300.            call wait_mutex      ;ebx
  301.  
  302.            mov edx, 0x1000
  303.            mov ebx, edi
  304.            shr ebx, 12
  305. @@:
  306.            mov [page_tabs+ebx*4], eax
  307.            invlpg [edi]
  308.            add edi, edx
  309.            add eax, edx
  310.            inc ebx
  311.            dec ecx
  312.            jnz @B
  313.            mov [pg_data.pg_mutex],ecx
  314. .fail:
  315.            ret
  316.  
  317.  
  318. ; param
  319. ;  eax= base
  320. ;  ecx= count
  321.  
  322. align 4
  323. release_pages:
  324.  
  325.            pushad
  326.            mov ebx, pg_data.pg_mutex
  327.            call wait_mutex      ;ebx
  328.  
  329.            mov esi, eax
  330.            mov edi, eax
  331.  
  332.            shr esi, 10
  333.            add esi, page_tabs
  334.  
  335.            mov ebp, [pg_data.pages_free]
  336.            mov ebx, [page_start]
  337.            mov edx, sys_pgmap
  338. @@:
  339.            xor eax, eax
  340.            xchg eax, [esi]
  341.            invlpg [edi]
  342.  
  343.            test eax, 1
  344.            jz .next
  345.  
  346.            shr eax, 12
  347.            bts [edx], eax
  348.            cmc
  349.            adc ebp, 0
  350.            shr eax, 3
  351.            and eax, -4
  352.            add eax, edx
  353.            cmp eax, ebx
  354.            jae .next
  355.  
  356.            mov ebx, eax
  357. .next:
  358.            add edi, 0x1000
  359.            add esi, 4
  360.            dec ecx
  361.            jnz @B
  362.            mov [pg_data.pages_free], ebp
  363.            and [pg_data.pg_mutex],0
  364.            popad
  365.            ret
  366.  
  367. align 4
  368. proc map_page_table stdcall, lin_addr:dword, phis_addr:dword
  369.            push ebx
  370.            mov ebx, [lin_addr]
  371.            shr ebx, 22
  372.            mov eax, [phis_addr]
  373.            and eax, not 0xFFF
  374.            or eax, PG_UW          ;+PG_NOCACHE
  375.            mov dword [master_tab+ebx*4], eax
  376.            mov eax, [lin_addr]
  377.            shr eax, 10
  378.            add eax, page_tabs
  379.            invlpg [eax]
  380.            pop ebx
  381.            ret
  382. endp
  383.  
  384. align 4
  385. proc init_LFB
  386.            locals
  387.              pg_count dd ?
  388.            endl
  389.  
  390.            cmp dword [LFBAddress], -1
  391.            jne @f
  392.            mov [BOOT_VAR+0x901c],byte 2
  393.            stdcall kernel_alloc, 0x280000
  394.            mov [LFBAddress], eax
  395.            ret
  396. @@:
  397.            test [SCR_MODE],word 0100000000000000b
  398.            jnz @f
  399.            mov [BOOT_VAR+0x901c],byte 2
  400.            ret
  401. @@:
  402.            mov edx, LFB_BASE
  403.            mov esi, [LFBAddress]
  404.            mov edi, [LFBSize]
  405.            mov dword [exp_lfb+4], edx
  406.  
  407.            shr edi, 12
  408.            mov [pg_count], edi
  409.            shr edi, 10
  410.  
  411.            bt [cpu_caps], CAPS_PSE
  412.            jnc .map_page_tables
  413.            or esi, PG_LARGE+PG_UW
  414.            shr edx, 20
  415.            mov ecx, edx
  416. @@:
  417.            mov [sys_pgdir+edx], esi
  418.            add edx, 4
  419.            add esi, 0x00400000
  420.            dec edi
  421.            jnz @B
  422.  
  423.            bt [cpu_caps], CAPS_PGE
  424.            jnc @F
  425.            or dword [sys_pgdir+ecx], PG_GLOBAL
  426. @@:
  427.            mov dword [LFBAddress], LFB_BASE
  428.            mov eax, cr3       ;flush TLB
  429.            mov cr3, eax
  430.            ret
  431.  
  432. .map_page_tables:
  433.  
  434.            call alloc_page
  435.            stdcall map_page_table, edx, eax
  436.            add edx, 0x00400000
  437.            dec edi
  438.            jnz .map_page_tables
  439.  
  440.            mov eax, [LFBAddress]
  441.            mov edi, page_tabs + (LFB_BASE shr 10)
  442.            or eax, PG_UW
  443.            mov ecx, [pg_count]
  444.            cld
  445. @@:
  446.            stosd
  447.            add eax, 0x1000
  448.            dec ecx
  449.            jnz @B
  450.  
  451.            mov dword [LFBAddress], LFB_BASE
  452.            mov eax, cr3       ;flush TLB
  453.            mov cr3, eax
  454.  
  455.            ret
  456. endp
  457.  
  458. align 4
  459. proc new_mem_resize stdcall, new_size:dword
  460.  
  461.            mov ebx, pg_data.pg_mutex
  462.            call wait_mutex    ;ebx
  463.  
  464.            mov edi, [new_size]
  465.            add edi,4095
  466.            and edi,not 4095
  467.            mov [new_size], edi
  468.  
  469.            mov edx,[CURRENT_TASK]
  470.            shl edx,8
  471.            cmp [SLOT_BASE+APPDATA.heap_base+edx],0
  472.            jne .exit
  473.  
  474.            mov esi, [SLOT_BASE+APPDATA.mem_size+edx]
  475.            add esi, 4095
  476.            and esi, not 4095
  477.  
  478.            cmp edi, esi
  479.            jae .expand
  480.  
  481.            shr edi, 12
  482.            shr esi, 12
  483. @@:
  484.            mov eax, [app_page_tabs+edi*4]
  485.            test eax, 1
  486.            jz .next
  487.            mov dword [app_page_tabs+edi*4], 2
  488.            mov ebx, edi
  489.            shl ebx, 12
  490.            invlpg [ebx+std_application_base_address]
  491.            call free_page
  492.  
  493. .next:     add edi, 1
  494.            cmp edi, esi
  495.            jb @B
  496.  
  497. .update_size:
  498.         mov     ebx, [new_size]
  499.         call    update_mem_size
  500.  
  501.            xor eax, eax
  502.            dec [pg_data.pg_mutex]
  503.            ret
  504.  
  505. .expand:
  506.            add edi, new_app_base
  507.            add esi, new_app_base
  508.  
  509.            push esi
  510.            push edi
  511.  
  512.            add edi, 0x3FFFFF
  513.            and edi, not(0x3FFFFF)
  514.            add esi, 0x3FFFFF
  515.            and esi, not(0x3FFFFF)
  516.  
  517.            cmp esi, edi
  518.            jae .grow
  519.  
  520.            xchg esi, edi
  521.  
  522. @@:
  523.            call alloc_page
  524.            test eax, eax
  525.            jz .exit
  526.  
  527.            stdcall map_page_table, edi, eax
  528.  
  529.            push edi
  530.            shr edi, 10
  531.            add edi, page_tabs
  532.            mov ecx, 1024
  533.            xor eax, eax
  534.            cld
  535.            rep stosd
  536.            pop edi
  537.  
  538.            add edi, 0x00400000
  539.            cmp edi, esi
  540.            jb @B
  541. .grow:
  542.            pop edi
  543.            pop esi
  544. @@:
  545.            call alloc_page
  546.            test eax, eax
  547.            jz .exit
  548.            stdcall map_page,esi,eax,dword PG_UW
  549.  
  550.            push edi
  551.            mov edi, esi
  552.            xor eax, eax
  553.            mov ecx, 1024
  554.            cld
  555.            rep stosd
  556.            pop edi
  557.  
  558.            add esi, 0x1000
  559.            cmp esi, edi
  560.            jb  @B
  561.  
  562.            jmp .update_size
  563. .exit:
  564.            xor eax, eax
  565.            inc eax
  566.            dec [pg_data.pg_mutex]
  567.            ret
  568. endp
  569.  
  570. update_mem_size:
  571. ; in: edx = slot shl 8
  572. ;     ebx = new memory size
  573. ; destroys eax,ecx,edx
  574.  
  575.            mov    [SLOT_BASE+APPDATA.mem_size+edx],ebx
  576. ;search threads and update
  577. ;application memory size infomation
  578.            mov    ecx,[SLOT_BASE+APPDATA.dir_table+edx]
  579.            mov    eax,2
  580.  
  581. .search_threads:
  582. ;eax = current slot
  583. ;ebx = new memory size
  584. ;ecx = page directory
  585.            cmp    eax,[TASK_COUNT]
  586.            jg     .search_threads_end
  587.            mov    edx,eax
  588.            shl    edx,5
  589.            cmp    word [CURRENT_TASK+edx+TASKDATA.state],9 ;if slot empty?
  590.            jz     .search_threads_next
  591.            shl    edx,3
  592.            cmp    [SLOT_BASE+edx+APPDATA.dir_table],ecx     ;if it is our thread?
  593.            jnz    .search_threads_next
  594.            mov    [SLOT_BASE+edx+APPDATA.mem_size],ebx     ;update memory size
  595. .search_threads_next:
  596.            inc    eax
  597.            jmp    .search_threads
  598. .search_threads_end:
  599.            ret
  600.  
  601. ; param
  602. ;  eax= linear address
  603. ;
  604. ; retval
  605. ;  eax= phisical page address
  606.  
  607. align 4
  608. get_pg_addr:
  609.            shr eax, 12
  610.            mov eax, [page_tabs+eax*4]
  611.            and eax, 0xFFFFF000
  612.            ret
  613.  
  614. align 4
  615. proc page_fault_handler
  616.            pushad
  617.  
  618.            mov ebp, esp
  619.            mov eax, cr2
  620.            push eax
  621.            push ds
  622.            push es
  623.  
  624.            mov ax, 0x10
  625.            mov ds, ax
  626.            mov es, ax
  627.  
  628.            inc [pg_data.pages_faults]
  629.  
  630.            mov ebx, [ebp-4]
  631.  
  632.            cmp ebx, 0x80000000
  633.            jae .user_space
  634.  
  635.            cmp ebx, app_page_tabs
  636.            jae .alloc
  637.  
  638.            cmp ebx, page_tabs
  639.            jae .tab_space
  640.  
  641.            cmp ebx, 0x7DC00000
  642.            jae .lfb_addr
  643.  
  644.            jmp .kernel_space
  645.  
  646. .user_space:
  647.            shr ebx, 12
  648.            mov ecx, ebx
  649.            shr ecx, 10
  650.            mov edx, [master_tab+ecx*4]
  651.            test edx, 1
  652.            jz .fail
  653.  
  654.            mov eax, [page_tabs+ebx*4]
  655.            test eax, 2
  656.            jz .fail
  657. .alloc:
  658.            call alloc_page
  659.            and eax, eax
  660.            jz .exit
  661.  
  662.            stdcall map_page,[ebp-4],eax,dword PG_UW
  663.  
  664.            mov edi, [ebp-4]
  665.            and edi, 0xFFFFF000
  666.            mov ecx, 1024
  667.            xor eax, eax
  668.            cld
  669.            rep stosd
  670. .exit:
  671.            pop es
  672.            pop ds
  673.            mov esp, ebp
  674.            popad
  675.            add esp, 4
  676.            iretd
  677. .fail:
  678.            pop es
  679.            pop ds
  680.            mov esp, ebp
  681.            popad
  682.            add esp, 4
  683.  
  684.            save_ring3_context     ;debugger support
  685.  
  686.            mov bl, 14
  687.            jmp exc_c
  688.            iretd
  689.  
  690. .kernel_space:
  691. ;           shr ebx, 12
  692. ;           mov eax, [page_tabs+ebx*4]
  693. ;           shr ebx, 10
  694. ;           mov eax, [master_tab+ebx*4]
  695.            jmp .exit
  696. .old_addr:
  697. ;           shr ebx, 12
  698. ;           mov eax, [page_tabs+ebx*4]
  699. ;           shr ebx, 10
  700. ;           mov eax, [master_tab+ebx*4]
  701.            jmp .exit
  702. .lfb_addr:
  703. ;           shr ebx, 22
  704. ;           ;mov ecx, [sys_page_dir]
  705. ;           mov eax, [master_tab+ebx*4]
  706.            jmp .exit
  707. .tab_space:
  708. ;           shr ebx, 12
  709. ;           mov eax, [page_tabs+ebx*4]
  710. ;           shr ebx, 10
  711. ;           ;mov ecx, [sys_page_dir]
  712. ;           mov eax, [master_tab+ebx*4]
  713.            jmp .exit
  714. endp
  715.  
  716. align 4
  717. proc map_mem stdcall, lin_addr:dword,pdir:dword,\
  718.                       ofs:dword,buf_size:dword
  719.            mov eax, [buf_size]
  720.            test eax, eax
  721.            jz .exit
  722.  
  723.            mov eax, [pdir]
  724.            and eax, 0xFFFFF000
  725.  
  726.            stdcall map_page,[ipc_pdir],eax,dword PG_UW
  727.            mov ebx, [ofs]
  728.            shr ebx, 22
  729.            mov esi, [ipc_pdir]
  730.            mov edi, [ipc_ptab]
  731.            mov eax, [esi+ebx*4]
  732.            and eax, 0xFFFFF000
  733.            test eax, eax
  734.            jz .exit
  735.            stdcall map_page,edi,eax,dword PG_UW
  736. ;           inc ebx
  737. ;           add edi, 0x1000
  738. ;           mov eax, [esi+ebx*4]
  739. ;           test eax, eax
  740. ;           jz @f
  741. ;          and eax, 0xFFFFF000
  742. ;           stdcall map_page, edi, eax
  743.  
  744. @@:        mov edi, [lin_addr]
  745.            and edi, 0xFFFFF000
  746.            mov ecx, [buf_size]
  747.            add ecx, 4095
  748.            shr ecx, 12
  749.            inc ecx
  750.  
  751.            mov edx, [ofs]
  752.            shr edx, 12
  753.            and edx, 0x3FF
  754.            mov esi, [ipc_ptab]
  755.  
  756. .map:      mov eax, [esi+edx*4]
  757.            and eax, 0xFFFFF000
  758.            test eax, eax
  759.            jz .exit
  760.            stdcall map_page,edi,eax,dword PG_UW
  761.            add edi, 0x1000
  762.            inc edx
  763.            dec ecx
  764.            jnz .map
  765.  
  766. .exit:
  767.            ret
  768. endp
  769.  
  770. align 4
  771. proc map_memEx stdcall, lin_addr:dword,pdir:dword,\
  772.                         ofs:dword,buf_size:dword
  773.            mov eax, [buf_size]
  774.            test eax, eax
  775.            jz .exit
  776.  
  777.            mov eax, [pdir]
  778.            and eax, 0xFFFFF000
  779.  
  780.            stdcall map_page,[proc_mem_pdir],eax,dword PG_UW
  781.            mov ebx, [ofs]
  782.            shr ebx, 22
  783.            mov esi, [proc_mem_pdir]
  784.            mov edi, [proc_mem_tab]
  785.            mov eax, [esi+ebx*4]
  786.            and eax, 0xFFFFF000
  787.            test eax, eax
  788.            jz .exit
  789.            stdcall map_page,edi,eax,dword PG_UW
  790.  
  791. @@:        mov edi, [lin_addr]
  792.            and edi, 0xFFFFF000
  793.            mov ecx, [buf_size]
  794.            add ecx, 4095
  795.            shr ecx, 12
  796.            inc ecx
  797.  
  798.            mov edx, [ofs]
  799.            shr edx, 12
  800.            and edx, 0x3FF
  801.            mov esi, [proc_mem_tab]
  802.  
  803. .map:      mov eax, [esi+edx*4]
  804. ;           and eax, 0xFFFFF000
  805. ;           test eax, eax
  806. ;           jz .exit
  807.            stdcall map_page,edi,eax,dword PG_UW
  808.            add edi, 0x1000
  809.            inc edx
  810.            dec ecx
  811.            jnz .map
  812. .exit:
  813.            ret
  814. endp
  815.  
  816.  
  817.  
  818.  
  819. sys_IPC:
  820. ;input:
  821. ;  eax=1 - set ipc buffer area
  822. ;    ebx=address of buffer
  823. ;    ecx=size of buffer
  824. ;  eax=2 - send message
  825. ;    ebx=PID
  826. ;    ecx=address of message
  827. ;    edx=size of message
  828.  
  829.            cmp  eax,1
  830.            jne @f
  831.            call set_ipc_buff
  832.            mov [esp+36], eax
  833.            ret
  834. @@:
  835.            cmp eax, 2
  836.            jne @f
  837.            stdcall sys_ipc_send, ebx, ecx, edx
  838.            mov [esp+36], eax
  839.            ret
  840. @@:
  841.            xor eax, eax
  842.            not eax
  843.            mov [esp+36], eax
  844.            ret
  845.  
  846. align 4
  847. proc set_ipc_buff
  848.  
  849.            mov  eax,[CURRENT_TASK]
  850.            shl  eax,8
  851.            add  eax, SLOT_BASE
  852.            pushf
  853.            cli
  854.            mov  [eax+0xA0],ebx     ;set fields in extended information area
  855.            mov  [eax+0xA4],ecx
  856.  
  857.            add ebx,  new_app_base
  858.            add ecx, ebx
  859.            add ecx, 4095
  860.            and ecx, not 4095
  861.  
  862. .touch:    mov eax, [ebx]
  863.            add ebx, 0x1000
  864.            cmp ebx, ecx
  865.            jna .touch
  866.  
  867.            popf
  868.            xor eax, eax
  869.            ret
  870. endp
  871.  
  872. proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
  873.            locals
  874.              dst_slot   dd ?
  875.              dst_offset dd ?
  876.              buf_size   dd ?
  877.            endl
  878.  
  879.            pushf
  880.            cli
  881.  
  882.            mov  eax, [PID]
  883.            call pid_to_slot
  884.            test eax,eax
  885.            jz   .no_pid
  886.  
  887.            mov [dst_slot], eax
  888.            shl  eax,8
  889.            mov  edi,[eax+SLOT_BASE+0xa0]  ;is ipc area defined?
  890.            test edi,edi
  891.            jz   .no_ipc_area
  892.  
  893.            mov ebx, edi
  894.            add edi, new_app_base
  895.            and ebx, 0xFFF
  896.            mov [dst_offset], ebx
  897.  
  898.            mov esi, [eax+SLOT_BASE+0xa4]
  899.            mov [buf_size], esi
  900.  
  901.            stdcall map_mem, [ipc_tmp], [SLOT_BASE+eax+0xB8],\
  902.                              edi, esi
  903.  
  904.            mov edi, [dst_offset]
  905.            add edi, [ipc_tmp]
  906.            cmp dword [edi], 0
  907.            jnz  .ipc_blocked          ;if dword [buffer]<>0 - ipc blocked now
  908.  
  909.            mov ebx, dword [edi+4]
  910.            mov edx, ebx
  911.            add ebx, 8
  912.            add ebx, [msg_size]
  913.            cmp ebx, [buf_size]
  914.            ja .buffer_overflow         ;esi<0 - not enough memory in buffer
  915.  
  916.            mov dword [edi+4], ebx
  917.            mov eax,[TASK_BASE]
  918.            mov eax, [eax+0x04]         ;eax - our PID
  919.            mov edi, [dst_offset]
  920.            add edi, [ipc_tmp]
  921.            add edi, edx
  922.            mov [edi], eax
  923.            mov ecx, [msg_size]
  924.  
  925.            mov [edi+4], ecx
  926.            add edi, 8
  927.            mov esi, [msg_addr]
  928.            add esi, new_app_base
  929.            cld
  930.            rep movsb
  931.  
  932.            mov ebx, [ipc_tmp]
  933.            mov edx, ebx
  934.            shr ebx, 12
  935.            xor eax, eax
  936.            mov [page_tabs+ebx*4], eax
  937.            invlpg [edx]
  938.  
  939.            mov ebx, [ipc_pdir]
  940.            mov edx, ebx
  941.            shr ebx, 12
  942.            xor eax, eax
  943.            mov [page_tabs+ebx*4], eax
  944.            invlpg [edx]
  945.  
  946.            mov ebx, [ipc_ptab]
  947.            mov edx, ebx
  948.            shr ebx, 12
  949.            xor eax, eax
  950.            mov [page_tabs+ebx*4], eax
  951.            invlpg [edx]
  952.  
  953.            mov  eax, [dst_slot]
  954.            shl eax, 8
  955.            or   [eax+SLOT_BASE+0xA8],dword 0x40
  956.            cmp  dword [check_idle_semaphore],20
  957.            jge  .ipc_no_cis
  958.  
  959.            mov  dword [check_idle_semaphore],5
  960. .ipc_no_cis:
  961.            popf
  962.            xor eax, eax
  963.            ret
  964. .no_pid:
  965.            popf
  966.            mov  eax, 4
  967.            ret
  968. .no_ipc_area:
  969.            popf
  970.            xor eax, eax
  971.            inc eax
  972.            ret
  973. .ipc_blocked:
  974.            popf
  975.            mov  eax, 2
  976.            ret
  977. .buffer_overflow:
  978.            popf
  979.            mov  eax, 3
  980.            ret
  981. endp
  982.  
  983. align 4
  984. sysfn_meminfo:
  985.  
  986.            add ebx, new_app_base
  987.            cmp ebx, new_app_base
  988.            jb .fail
  989.  
  990.            mov eax, [pg_data.pages_count]
  991.            mov [ebx], eax
  992.            shl eax, 12
  993.            mov [esp+36], eax
  994.            mov ecx, [pg_data.pages_free]
  995.            mov [ebx+4], ecx
  996.            mov edx, [pg_data.pages_faults]
  997.            mov [ebx+8], edx
  998.            mov esi, [heap_size]
  999.            mov [ebx+12], esi
  1000.            mov edi, [heap_free]
  1001.            mov [ebx+16], edi
  1002.            mov eax, [heap_blocks]
  1003.            mov [ebx+20], eax
  1004.            mov ecx, [free_blocks]
  1005.            mov [ebx+24], ecx
  1006.            ret
  1007. .fail:
  1008.            mov dword [esp+36], -1
  1009.            ret
  1010.  
  1011. align 4
  1012. new_services:
  1013.  
  1014.            cmp  eax,4
  1015.            jle  sys_sheduler
  1016.  
  1017.            cmp eax, 11
  1018.            jb .fail
  1019.            ja @f
  1020.  
  1021.            call init_heap
  1022.            mov [esp+36], eax
  1023.            ret
  1024. @@:
  1025.            cmp eax, 12
  1026.            ja @f
  1027.  
  1028.            stdcall user_alloc, ebx
  1029.            mov [esp+36], eax
  1030.            ret
  1031. @@:
  1032.            cmp eax, 13
  1033.            ja @f
  1034.            add ebx, new_app_base
  1035.            stdcall user_free, ebx
  1036.            mov [esp+36], eax
  1037.            ret
  1038. @@:
  1039.            cmp eax, 14
  1040.            ja @f
  1041.            add ebx, new_app_base
  1042.            cmp ebx, new_app_base
  1043.            jb .fail
  1044.            stdcall get_event_ex, ebx, ecx
  1045.            mov [esp+36], eax
  1046.            ret
  1047. @@:
  1048.            cmp eax, 15
  1049.            ja @f
  1050.            mov ecx, [CURRENT_TASK]
  1051.            shl ecx, 8
  1052.            mov eax, [ecx+SLOT_BASE+APPDATA.fpu_handler]
  1053.            mov [ecx+SLOT_BASE+APPDATA.fpu_handler], ebx
  1054.            mov [esp+36], eax
  1055.            ret
  1056. @@:
  1057.            cmp eax, 16
  1058.            ja @f
  1059.  
  1060.            test ebx, ebx
  1061.            jz .fail
  1062.            add ebx, new_app_base
  1063.            cmp ebx, new_app_base
  1064.            jb .fail
  1065.            stdcall get_service, ebx
  1066.            mov [esp+36], eax
  1067.            ret
  1068. @@:
  1069.            cmp eax, 17
  1070.            ja @f
  1071.            call srv_handlerEx   ;ebx
  1072.            mov [esp+36], eax
  1073.            ret
  1074. @@:
  1075.            cmp eax, 18
  1076.            ja @f
  1077.            mov ecx, [CURRENT_TASK]
  1078.            shl ecx, 8
  1079.            mov eax, [ecx+SLOT_BASE+APPDATA.sse_handler]
  1080.            mov [ecx+SLOT_BASE+APPDATA.sse_handler], ebx
  1081.            mov [esp+36], eax
  1082.            ret
  1083. @@:
  1084.            cmp eax, 19
  1085.            ja .fail
  1086.            add ebx, new_app_base
  1087.            cmp ebx, new_app_base
  1088.            jb .fail
  1089.            stdcall load_library, ebx
  1090.            mov [esp+36], eax
  1091.            ret
  1092.  
  1093. .fail:
  1094.            xor eax, eax
  1095.            mov [esp+36], eax
  1096.            ret
  1097.  
  1098. align 4
  1099. proc strncmp stdcall, str1:dword, str2:dword, count:dword
  1100.  
  1101.           mov ecx,[count]
  1102.           jecxz .end
  1103.  
  1104.           mov ebx,ecx
  1105.  
  1106.           mov edi,[str1]
  1107.           mov esi,edi
  1108.           xor eax,eax
  1109.           repne scasb
  1110.           neg ecx             ; cx = count - strlen
  1111.           add ecx,ebx         ; strlen + count - strlen
  1112.  
  1113. .okay:
  1114.           mov edi,esi
  1115.           mov esi,[str2]
  1116.           repe cmpsb
  1117.           mov al,[esi-1]
  1118.           xor ecx,ecx
  1119.  
  1120.           cmp al,[edi-1]
  1121.           ja .str2_big
  1122.           je .end
  1123.  
  1124. .str1_big:
  1125.           sub ecx,2
  1126.  
  1127. .str2_big:
  1128.           not ecx
  1129. .end:
  1130.           mov eax,ecx
  1131.           ret
  1132. endp
  1133.  
  1134. align 4
  1135. proc test_cpu
  1136.            locals
  1137.               cpu_type   dd ?
  1138.               cpu_id     dd ?
  1139.               cpu_Intel  dd ?
  1140.               cpu_AMD    dd ?
  1141.            endl
  1142.  
  1143.            mov [cpu_type], 0
  1144.            xor eax, eax
  1145.            mov [cpu_caps], eax
  1146.            mov [cpu_caps+4], eax
  1147.  
  1148.            pushfd
  1149.            pop eax
  1150.            mov ecx, eax
  1151.            xor eax, 0x40000
  1152.            push eax
  1153.            popfd
  1154.            pushfd
  1155.            pop eax
  1156.            xor eax, ecx
  1157.            mov [cpu_type], CPU_386
  1158.            jz .end_cpuid
  1159.            push ecx
  1160.            popfd
  1161.  
  1162.            mov [cpu_type], CPU_486
  1163.            mov eax, ecx
  1164.            xor eax, 0x200000
  1165.            push eax
  1166.            popfd
  1167.            pushfd
  1168.            pop eax
  1169.            xor eax, ecx
  1170.            je .end_cpuid
  1171.            mov [cpu_id], 1
  1172.  
  1173.            xor eax, eax
  1174.            cpuid
  1175.            mov [cpu_vendor], ebx
  1176.            mov [cpu_vendor+4], edx
  1177.            mov [cpu_vendor+8], ecx
  1178.            cmp ebx, dword [intel_str]
  1179.            jne .check_AMD
  1180.            cmp edx, dword [intel_str+4]
  1181.            jne .check_AMD
  1182.            cmp ecx, dword [intel_str+8]
  1183.            jne .check_AMD
  1184.            mov [cpu_Intel], 1
  1185.            cmp eax, 1
  1186.            jl .end_cpuid
  1187.            mov eax, 1
  1188.            cpuid
  1189.            mov [cpu_sign], eax
  1190.            mov [cpu_info],  ebx
  1191.            mov [cpu_caps],  edx
  1192.            mov [cpu_caps+4],ecx
  1193.  
  1194.            shr eax, 8
  1195.            and eax, 0x0f
  1196.            ret
  1197. .end_cpuid:
  1198.            mov eax, [cpu_type]
  1199.            ret
  1200.  
  1201. .check_AMD:
  1202.            cmp ebx, dword [AMD_str]
  1203.            jne .unknown
  1204.            cmp edx, dword [AMD_str+4]
  1205.            jne .unknown
  1206.            cmp ecx, dword [AMD_str+8]
  1207.            jne .unknown
  1208.            mov [cpu_AMD], 1
  1209.            cmp eax, 1
  1210.            jl .unknown
  1211.            mov eax, 1
  1212.            cpuid
  1213.            mov [cpu_sign], eax
  1214.            mov [cpu_info],  ebx
  1215.            mov [cpu_caps],  edx
  1216.            mov [cpu_caps+4],ecx
  1217.            shr eax, 8
  1218.            and eax, 0x0f
  1219.            ret
  1220. .unknown:
  1221.            mov eax, 1
  1222.            cpuid
  1223.            mov [cpu_sign], eax
  1224.            mov [cpu_info],  ebx
  1225.            mov [cpu_caps],  edx
  1226.            mov [cpu_caps+4],ecx
  1227.            shr eax, 8
  1228.            and eax, 0x0f
  1229.            ret
  1230. endp
  1231.  
  1232. MEM_WB     equ 6               ;write-back memory
  1233. MEM_WC     equ 1               ;write combined memory
  1234. MEM_UC     equ 0               ;uncached memory
  1235.  
  1236. align 4
  1237. proc init_mtrr
  1238.  
  1239.            cmp [BOOT_VAR+0x901c],byte 2
  1240.            je  .exit
  1241.  
  1242.            bt [cpu_caps], CAPS_MTRR
  1243.            jnc .exit
  1244.  
  1245.            mov eax, cr0
  1246.            or eax, 0x60000000   ;disable caching
  1247.            mov cr0, eax
  1248.            wbinvd               ;invalidate cache
  1249.  
  1250.            mov ecx, 0x2FF
  1251.            rdmsr                ;
  1252.            push eax
  1253.  
  1254.            xor edx, edx
  1255.            xor eax, eax
  1256.            mov ecx, 0x2FF
  1257.            wrmsr                ;disable all MTRR
  1258.  
  1259.            stdcall set_mtrr, dword 0,dword 0,[MEM_AMOUNT],MEM_WB
  1260.            stdcall set_mtrr, dword 1,[LFBAddress],[LFBSize],MEM_WC
  1261.            xor edx, edx
  1262.            xor eax, eax
  1263.            mov ecx, 0x204
  1264.            mov ebx, 6
  1265. @@:
  1266.            wrmsr                ;disable unused MTRR
  1267.            inc ecx
  1268.            wrmsr
  1269.            inc ecx
  1270.            dec ebx
  1271.            jnz @b
  1272.  
  1273.            wbinvd               ;again invalidate
  1274.  
  1275.            pop eax
  1276.            or eax, 0x800        ;set default memtype to UC
  1277.            and al, 0xF0
  1278.            mov ecx, 0x2FF
  1279.            wrmsr                ;and enable MTRR
  1280.  
  1281.            mov eax, cr0
  1282.            and eax, not 0x60000000
  1283.            mov cr0, eax         ; enable caching
  1284. .exit:
  1285.            ret
  1286. endp
  1287.  
  1288. align 4
  1289. proc set_mtrr stdcall, reg:dword,base:dword,size:dword,mem_type:dword
  1290.  
  1291.            xor edx, edx
  1292.            mov eax, [base]
  1293.            or eax, [mem_type]
  1294.            mov ecx, [reg]
  1295.            lea ecx, [0x200+ecx*2]
  1296.            wrmsr
  1297.  
  1298.            mov ebx, [size]
  1299.            dec ebx
  1300.            mov eax, 0xFFFFFFFF
  1301.            mov edx, 0x0000000F
  1302.            sub eax, ebx
  1303.            sbb edx, 0
  1304.            or eax, 0x800
  1305.            inc ecx
  1306.            wrmsr
  1307.            ret
  1308. endp
  1309.  
  1310. align 4
  1311. proc stall stdcall, delay:dword
  1312.            push ecx
  1313.            push edx
  1314.            push ebx
  1315.            push eax
  1316.  
  1317.            mov eax, [delay]
  1318.            mul [stall_mcs]
  1319.            mov ebx, eax       ;low
  1320.            mov ecx, edx       ;high
  1321.            rdtsc
  1322.            add ebx, eax
  1323.            adc ecx,edx
  1324. @@:
  1325.            rdtsc
  1326.            sub eax, ebx
  1327.            sbb edx, ecx
  1328.            jb @B
  1329.  
  1330.            pop eax
  1331.            pop ebx
  1332.            pop edx
  1333.            pop ecx
  1334.            ret
  1335. endp
  1336.  
  1337. iglobal
  1338. align 4
  1339.   intel_str    db "GenuineIntel",0
  1340.   AMD_str      db "AuthenticAMD",0
  1341. endg
  1342.  
  1343. uglobal
  1344. align 16
  1345.   irq_tab           rd 16
  1346.  
  1347.   MEM_FreeSpace     rd 1
  1348.  
  1349.   ipc_tmp           rd 1
  1350.   ipc_pdir          rd 1
  1351.   ipc_ptab          rd 1
  1352.  
  1353.   proc_mem_map      rd 1
  1354.   proc_mem_pdir     rd 1
  1355.   proc_mem_tab      rd 1
  1356.  
  1357.   tmp_task_pdir     rd 1
  1358.   tmp_task_ptab     rd 1
  1359.  
  1360.   fdd_buff          rd 1
  1361.   LFBSize           rd 1
  1362.  
  1363.   stall_mcs         rd 1
  1364. ;;CPUID information
  1365.  
  1366.   cpu_vendor        rd 3
  1367.   cpu_sign          rd 1
  1368.   cpu_info          rd 1
  1369.  
  1370. ;;;;;   cursors data
  1371.  
  1372. align 16
  1373. cur_saved_data   rb 4096
  1374.  
  1375. def_cursor       rd 1
  1376. hw_cursor        rd 1
  1377.  
  1378. scr_width        rd 1
  1379. scr_height       rd 1
  1380.  
  1381. cur_def_interl   rd 1
  1382. cur_saved_base   rd 1
  1383. cur_saved_interl rd 1
  1384. cur_saved_w      rd 1
  1385. cur_saved_h      rd 1
  1386.  
  1387. endg
  1388.  
  1389. uglobal
  1390. align 16
  1391.    fpu_data:
  1392.                    rb 512
  1393.  
  1394.    mst MEM_STATE
  1395.  
  1396.    mem_block_map   rb 512
  1397.    event_map       rb 64
  1398.    mem_block_list  rd 64
  1399.    mem_block_mask  rd 2
  1400.  
  1401.    srv.fd          rd 1
  1402.    srv.bk          rd 1
  1403.  
  1404.    mem_used.fd     rd 1
  1405.    mem_used.bk     rd 1
  1406.  
  1407.    mem_block_arr   rd 1
  1408.    mem_block_start rd 1
  1409.    mem_block_end   rd 1
  1410.  
  1411.    heap_mutex      rd 1
  1412.    heap_size       rd 1
  1413.    heap_free       rd 1
  1414.    heap_blocks     rd 1
  1415.    free_blocks     rd 1
  1416.  
  1417.    page_start      rd 1
  1418.    page_end        rd 1
  1419.    events          rd 1
  1420.    event_start     rd 1
  1421.    event_end       rd 1
  1422.    event_uid       rd 1
  1423.    sys_page_map    rd 1
  1424.    os_stack        rd 1
  1425. endg
  1426.  
  1427. if 0
  1428.      push eax
  1429.      push edx
  1430.      mov edx, 0x400   ;bocsh
  1431.      mov al,0xff      ;bocsh
  1432.      out dx, al       ;bocsh
  1433.      pop edx
  1434.      pop eax
  1435. end if
  1436.  
  1437. align 4
  1438. k_strrchr:
  1439.         push eax
  1440.         xor eax,eax
  1441.         or  ecx,-1
  1442.         repne scasb
  1443.         add ecx,1
  1444.         neg ecx
  1445.         sub edi,1
  1446.         pop eax
  1447.         std
  1448.         repne scasb
  1449.         cld
  1450.         add edi,1
  1451.  
  1452.         cmp [edi],al
  1453.         jne @F
  1454.         mov eax,edi
  1455.         ret
  1456. @@:
  1457.         xor eax,eax
  1458.         ret
  1459.  
  1460. align 4
  1461. proc k_strncpy stdcall, dest:dword, src:dword, maxlen:dword
  1462.         mov eax, [dest]
  1463.         mov esi, [src]
  1464.         mov ecx, [maxlen]
  1465.         test eax, eax
  1466.         jz .L9
  1467.         test esi, esi
  1468.         jz .L9
  1469.         test ecx, ecx
  1470.         jz .L9
  1471.  
  1472.         sub  esi, eax
  1473.         jmp .L1
  1474.  
  1475. align 4
  1476. .L2:
  1477.         mov edx, [esi+eax]
  1478.         mov [eax], dl
  1479.         test dl, dl
  1480.         jz .L7
  1481.  
  1482.         mov [eax+1], dh
  1483.         test dh, dh
  1484.         jz .L6
  1485.  
  1486.         shr edx, 16
  1487.         mov [eax+2],dl
  1488.         test dl, dl
  1489.         jz .L5
  1490.  
  1491.         mov [eax+3], dh
  1492.         test dh, dh
  1493.         jz .L4
  1494.         add eax, 4
  1495. .L1:
  1496.         sub ecx, 4
  1497.         jae .L2
  1498.  
  1499.         add ecx, 4
  1500.         jz .L9
  1501.  
  1502.         mov dl, [eax+esi]
  1503.         mov [eax], dl
  1504.         test dl, dl
  1505.         jz .L3
  1506.  
  1507.         inc eax
  1508.         dec ecx
  1509.         jz .L9
  1510.  
  1511.         mov dl, [eax+esi]
  1512.         mov [eax], dl
  1513.         test dl, dl
  1514.         jz .L3
  1515.  
  1516.         inc eax
  1517.         dec ecx
  1518.         jz .L9
  1519.  
  1520.         mov dl, [eax+esi]
  1521.         mov [eax], dl
  1522.         test dl, dl
  1523.         jz .L3
  1524.  
  1525.         inc eax
  1526.         jmp .L9
  1527.  
  1528. .L4:    dec ecx
  1529.         inc eax
  1530.  
  1531. .L5:    dec ecx
  1532.         inc eax
  1533.  
  1534. .L6:    dec ecx
  1535.         inc eax
  1536. .L7:
  1537.         add ecx,3
  1538.         jz .L9
  1539. .L8:
  1540.         mov byte [ecx+eax], 0
  1541. .L3:
  1542.         dec ecx
  1543.         jnz .L8
  1544. .L9:
  1545.         ret
  1546. endp
  1547.  
  1548. if 0
  1549.  
  1550. magic equ 0xfefefeff
  1551.  
  1552. k_strlen:
  1553.         mov eax,[esp+4]
  1554.         mov edx, 3
  1555.  
  1556.         and edx, eax
  1557.         jz .L1
  1558.         jp .L0
  1559.  
  1560.         cmp dh, byte [eax]
  1561.         je .L2
  1562.  
  1563.         inc eax
  1564.         cmp dh, byte [eax]
  1565.  
  1566.         je .L2
  1567.  
  1568.         inc eax
  1569.         xor edx, 2
  1570.  
  1571.         jz .L1
  1572. .L0:
  1573.         cmp dh, [eax]
  1574.         je .L2
  1575.  
  1576.         inc eax
  1577.         xor edx, edx
  1578.  
  1579. .L1:
  1580.         mov ecx, [eax]
  1581.         add eax, 4
  1582.  
  1583.         sub edx, ecx
  1584.         add ecx, magic
  1585.  
  1586.         dec edx
  1587.         jnc .L3
  1588.  
  1589.         xor edx, ecx
  1590.         and edx, not magic
  1591.         jne .L3
  1592.  
  1593.         mov ecx, [eax]
  1594.         add eax, 4
  1595.  
  1596.         sub edx, ecx
  1597.         add ecx, magic
  1598.         dec edx
  1599.         jnc .L3
  1600.  
  1601.         xor edx, ecx
  1602.         and edx, not magic
  1603.         jne .L3
  1604.  
  1605.         mov ecx, [eax]
  1606.         add eax, 4
  1607.  
  1608.         sub edx, ecx
  1609.         add ecx, magic
  1610.  
  1611.         dec edx
  1612.         jnc .L3
  1613.  
  1614.         xor edx, ecx
  1615.  
  1616.         and edx, not magic
  1617.         jne .L3
  1618.  
  1619.         mov ecx, [eax]
  1620.         add eax, 4
  1621.  
  1622.         sub edx, ecx
  1623.         add ecx, magic
  1624.  
  1625.         dec edx
  1626.         jnc .L3
  1627.  
  1628.         xor edx, ecx
  1629.  
  1630.         and edx, not magic
  1631.         je .L1
  1632.  
  1633. .L3:    sub eax ,4
  1634.         sub ecx, magic
  1635.  
  1636.         cmp cl, 0
  1637.         jz .L2
  1638.  
  1639.         inc eax
  1640.         test ch, ch
  1641.         jz .L2
  1642.  
  1643.         shr ecx, 16
  1644.         inc eax
  1645.  
  1646.         cmp cl,0
  1647.         jz .L2
  1648.  
  1649.         inc eax
  1650.  
  1651. .L2:
  1652.         sub eax, [esp+4]
  1653.         ret
  1654.  
  1655. end if
  1656.