Subversion Repositories Kolibri OS

Rev

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