Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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