Subversion Repositories Kolibri OS

Rev

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