Subversion Repositories Kolibri OS

Rev

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

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