Subversion Repositories Kolibri OS

Rev

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