Subversion Repositories Kolibri OS

Rev

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

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