Subversion Repositories Kolibri OS

Rev

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

  1.  
  2. HEAP_BASE equ 0x00C00000
  3. ;HEAP_SIZE equ 0x01000000
  4.  
  5. struc MEM_BLOCK
  6. {  .next_block  dd ?
  7.    .prev_block  dd ? ;+4
  8.    .list_next   dd ? ;+8
  9.    .list_prev   dd ? ;+12
  10.    .base        dd ? ;+16
  11.    .size        dd ? ;+20
  12.    .flags       dd ? ;+24
  13.    .handle      dd ? ;+28
  14. }
  15.  
  16. FREE_BLOCK      equ  4
  17. USED_BLOCK      equ  8
  18.  
  19. virtual at 0
  20.   MEM_BLOCK MEM_BLOCK
  21. end virtual
  22.  
  23. MEM_BLOCK_SIZE equ 8*4
  24.  
  25. block_next   equ MEM_BLOCK.next_block
  26. block_prev   equ MEM_BLOCK.prev_block
  27. list_next    equ MEM_BLOCK.list_next
  28. list_prev    equ MEM_BLOCK.list_prev
  29. block_base   equ MEM_BLOCK.base
  30. block_size   equ MEM_BLOCK.size
  31. block_flags  equ MEM_BLOCK.flags
  32.  
  33. macro calc_index op
  34. {          shr op, 12
  35.            dec op
  36.            cmp op, 63
  37.            jna @f
  38.            mov op, 63
  39. @@:
  40. }
  41.  
  42. macro remove_from_list op
  43. {          mov edx, [op+list_next]
  44.            mov ecx, [op+list_prev]
  45.            test edx, edx
  46.            jz @f
  47.            mov [edx+list_prev], ecx
  48. @@:
  49.            test ecx, ecx
  50.            jz @f
  51.            mov [ecx+list_next], edx
  52. @@:
  53.            mov [op+list_next],0
  54.            mov [op+list_prev],0
  55. }
  56.  
  57. macro remove_from_free op
  58. {
  59.            remove_from_list op
  60.  
  61.            mov eax, [op+block_size]
  62.            calc_index eax
  63.            cmp [mem_block_list+eax*4], op
  64.            jne @f
  65.            mov [mem_block_list+eax*4], edx
  66. @@:
  67.            cmp [mem_block_list+eax*4], 0
  68.            jne @f
  69.            btr [mem_block_mask], eax
  70. @@:
  71. }
  72.  
  73. macro remove_from_used op
  74. {
  75.            remove_from_list op
  76.            cmp [mem_used_list], op
  77.            jne @f
  78.            mov [mem_used_list], edx
  79. @@:
  80. }
  81.  
  82. align 4
  83. proc init_kernel_heap
  84.  
  85.            mov ecx, 64/4
  86.            mov edi, mem_block_list
  87.            xor eax, eax
  88.            cld
  89.            rep stosd
  90.  
  91.            mov ecx, 512/4
  92.            mov edi, mem_block_map
  93.            not eax
  94.            rep stosd
  95.  
  96.            mov [mem_block_start], mem_block_map
  97.            mov [mem_block_end], mem_block_map+512
  98.            mov [mem_block_arr], HEAP_BASE
  99.  
  100.            stdcall alloc_pages, dword 32
  101.            mov ecx, 32
  102.            mov edx, eax
  103.            mov edi, HEAP_BASE
  104. .l1:
  105.            stdcall map_page,edi,edx,PG_SW
  106.            add edi, 0x1000
  107.            add edx, 0x1000
  108.            dec ecx
  109.            jnz .l1
  110.  
  111.            mov edi, HEAP_BASE
  112.            mov ebx, edi
  113.            add ebx, MEM_BLOCK_SIZE
  114.            xor eax, eax
  115.            mov [edi+block_next], ebx
  116.            mov [edi+block_prev], eax
  117.            mov [edi+list_next], eax
  118.            mov [edi+list_prev], eax
  119.            mov [edi+block_base], HEAP_BASE
  120.            mov [edi+block_size], 4096*MEM_BLOCK_SIZE
  121.            mov [edi+block_flags], USED_BLOCK
  122.  
  123.            mov [ebx+block_next], eax
  124.            mov [ebx+block_prev], eax
  125.            mov [ebx+list_next], eax
  126.            mov [ebx+block_base], HEAP_BASE+4096*MEM_BLOCK_SIZE
  127.  
  128.            mov ecx, [MEM_AMOUNT]
  129.            sub ecx, HEAP_BASE + 4096*MEM_BLOCK_SIZE
  130.            mov [heap_size], ecx
  131.            mov [heap_free], ecx
  132.            mov [ebx+block_size], ecx
  133.            mov [ebx+block_flags], FREE_BLOCK
  134.  
  135.            mov [mem_block_mask], eax
  136.            mov [mem_block_mask+4],0x80000000
  137.  
  138.            mov [mem_used_list], eax
  139.            mov [mem_block_list+63*4], ebx
  140.            mov byte [mem_block_map], 0xFC
  141.            and [heap_mutex], 0
  142.            mov [heap_blocks], 4095
  143.            mov [free_blocks], 4095
  144.            ret
  145. endp
  146.  
  147. align 4
  148. proc get_block stdcall, index:dword
  149.  
  150.            mov eax, 63
  151.            mov ecx, [index]
  152.            cmp ecx, eax
  153.            jna @f
  154.            ;cmova ecx, eax
  155.            mov ecx, eax
  156. @@:
  157.            xor esi, esi
  158.            xor ebx, ebx
  159.            xor edx, edx
  160.            not edx
  161.  
  162.            cmp ecx, 32
  163.            jb .bit_test
  164.  
  165.            sub ecx, 32
  166.            add ebx, 32
  167.            add esi, 4
  168.  
  169. .bit_test:
  170.            shl edx, cl
  171.            and edx, [mem_block_mask+esi]
  172.            jz .high_mask
  173.            bsf eax, edx
  174.            add ebx, eax
  175.            mov eax, [mem_block_list+ebx*4]
  176.            ret
  177.  
  178. .high_mask:
  179.  
  180.            add esi, 4
  181.            add ebx, 32
  182.            test esi, 0xFFFFFFF8
  183.            jnz .big_error
  184.            mov edx, [mem_block_mask+esi]
  185.            and edx, edx
  186.            jz .high_mask
  187.            bsf eax, edx
  188.            add ebx, eax
  189.            mov eax, [mem_block_list+ebx*4]
  190.            ret
  191.  
  192. .big_error:
  193.            xor eax, eax
  194.            ret
  195. endp
  196.  
  197. align 4
  198. proc alloc_mem_block
  199.  
  200.            mov ebx, [mem_block_start]
  201.            mov ecx, [mem_block_end]
  202. .l1:
  203.            bsf eax,[ebx];
  204.            jnz found
  205.            add ebx,4
  206.            cmp ebx, ecx
  207.            jb .l1
  208.            xor eax,eax
  209.            ret
  210.  
  211. found:
  212.            btr [ebx], eax
  213.            mov [mem_block_start],ebx
  214.            sub ebx, mem_block_map
  215.            lea eax,[eax+ebx*8]
  216.            shl eax, 5
  217.            add eax, [mem_block_arr]
  218.            dec [free_blocks]
  219.            ret
  220. endp
  221.  
  222. proc free_mem_block
  223.            sub eax, [mem_block_arr]
  224.            shr eax, 5
  225.  
  226.            mov ebx, mem_block_map
  227.            bts [ebx], eax
  228.            inc [free_blocks]
  229.            shr eax, 3
  230.            and eax, not 3
  231.            add eax, ebx
  232.            cmp [mem_block_start], eax
  233.            ja @f
  234.            ret
  235. @@:
  236.            mov [mem_block_start], eax
  237.            ret
  238. .err:
  239.            xor eax, eax
  240.            ret
  241. endp
  242.  
  243. align 4
  244. proc alloc_kernel_space stdcall, size:dword
  245.            local block_ind:DWORD
  246.  
  247.            mov eax, [size]
  248.            add eax, 4095
  249.            and eax, not 4095
  250.            mov [size], eax
  251.  
  252.            mov ebx, heap_mutex
  253.            call wait_mutex    ;ebx
  254.  
  255.            cmp eax, [heap_free]
  256.            ja .error
  257.  
  258.            shr eax, 12
  259.            sub eax, 1
  260.  
  261.            mov [block_ind], eax
  262.  
  263.            stdcall get_block, eax
  264.            test eax, eax
  265.            jz .error
  266.  
  267.            mov edi, eax           ;edi - pBlock
  268.  
  269.            cmp [edi+block_flags], FREE_BLOCK
  270.            jne .error
  271.  
  272.            mov [block_ind], ebx   ;index of allocated block
  273.  
  274.            mov eax, [edi+block_size]
  275.            cmp eax, [size]
  276.            je .m_eq_size
  277.  
  278.            call alloc_mem_block
  279.            and eax, eax
  280.            jz .error
  281.  
  282.            mov esi, eax           ;esi - splitted block
  283.  
  284.            mov [esi+block_next], edi
  285.            mov eax, [edi+block_prev]
  286.            mov [esi+block_prev], eax
  287.            mov [edi+block_prev], esi
  288.            mov [esi+list_next], 0
  289.            mov [esi+list_prev], 0
  290.            and eax, eax
  291.            jz @f
  292.            mov [eax+block_next], esi
  293. @@:
  294.            mov ebx, [edi+block_base]
  295.            mov [esi+block_base], ebx
  296.            mov edx, [size]
  297.            mov [esi+block_size], edx
  298.            add [edi+block_base], edx
  299.            sub [edi+block_size], edx
  300.  
  301.            mov eax, [edi+block_size]
  302.            shr eax, 12
  303.            sub eax, 1
  304.            cmp eax, 63
  305.            jna @f
  306.            mov eax, 63
  307. @@:
  308.            cmp eax, [block_ind]
  309.            je .m_eq_ind
  310.  
  311.            remove_from_list edi
  312.  
  313.            mov ecx, [block_ind]
  314.            mov [mem_block_list+ecx*4], edx
  315.  
  316.            test edx, edx
  317.            jnz @f
  318.            btr [mem_block_mask], ecx
  319. @@:
  320.            mov edx, [mem_block_list+eax*4]
  321.            mov [edi+list_next], edx
  322.            test edx, edx
  323.            jz @f
  324.            mov [edx+list_prev], edi
  325. @@:
  326.            mov [mem_block_list+eax*4], edi
  327.            bts [mem_block_mask], eax
  328. .m_eq_ind:
  329.            mov ebx, [mem_used_list]
  330.            mov [esi+list_next], ebx
  331.            test ebx, ebx
  332.            jz @f
  333.            mov [ebx+list_prev], esi
  334. @@:
  335.            mov [esi+block_flags], USED_BLOCK
  336.            mov [mem_used_list], esi
  337.            mov eax, [esi+block_base]
  338.            mov ebx, [size]
  339.            sub [heap_free], ebx
  340.            and [heap_mutex], 0
  341.            ret
  342. .m_eq_size:
  343.            remove_from_list edi
  344.            mov [mem_block_list+ebx*4], edx
  345.            and edx, edx
  346.            jnz @f
  347.            btr [mem_block_mask], ebx
  348. @@:
  349.            mov ecx, [mem_used_list]
  350.            mov [edi+list_next], ecx
  351.            test ecx, ecx
  352.            jnz @f
  353.            mov [ecx+list_prev], edi
  354. @@:
  355.            mov [mem_used_list], edi
  356.            mov [edi+block_flags], USED_BLOCK
  357.            mov eax, [edi+block_base]
  358.            mov ebx, [size]
  359.            sub [heap_free], ebx
  360.            and [heap_mutex], 0
  361.            ret
  362. .error:
  363.            xor eax, eax
  364.            mov [heap_mutex], eax
  365.            ret
  366. endp
  367.  
  368. align 4
  369. proc free_kernel_space stdcall, base:dword
  370.  
  371.            mov ebx, heap_mutex
  372.            call wait_mutex    ;ebx
  373.  
  374.            mov eax, [base]
  375.            mov esi, [mem_used_list]
  376. @@:
  377.            test esi, esi
  378.            jz .fail
  379.  
  380.            cmp [esi+block_base], eax
  381.            je .found
  382.            mov esi, [esi+list_next]
  383.            jmp @b
  384. .found:
  385.            cmp [esi+block_flags], USED_BLOCK
  386.            jne .fail
  387.  
  388.            mov eax, [esi+block_size]
  389.            add [heap_free], eax
  390.  
  391.            mov edi, [esi+block_next]
  392.            test edi, edi
  393.            jz .prev
  394.  
  395.            cmp [edi+block_flags], FREE_BLOCK
  396.            jne .prev
  397.  
  398.            remove_from_free edi
  399.  
  400.            mov edx, [edi+block_next]
  401.            mov [esi+block_next], edx
  402.            test edx, edx
  403.            jz @f
  404.  
  405.            mov [edx+block_prev], esi
  406. @@:
  407.            mov ecx, [edi+block_size]
  408.            add [esi+block_size], ecx
  409.  
  410.            mov eax, edi
  411.            call free_mem_block
  412. .prev:
  413.            mov edi, [esi+block_prev]
  414.            test edi, edi
  415.            jz .insert
  416.  
  417.            cmp [edi+block_flags], FREE_BLOCK
  418.            jne .insert
  419.  
  420.            remove_from_used esi
  421.  
  422.            mov edx, [esi+block_next]
  423.            mov [edi+block_next], edx
  424.            test edx, edx
  425.            jz @f
  426.            mov [edx+block_prev], edi
  427. @@:
  428.            mov eax, esi
  429.            call free_mem_block
  430.  
  431.            mov ecx, [edi+block_size]
  432.            mov eax, [esi+block_size]
  433.            add eax, ecx
  434.            mov [edi+block_size], eax
  435.  
  436.            calc_index eax
  437.            calc_index ecx
  438.            cmp eax, ecx
  439.            je .m_eq
  440.  
  441.            push ecx
  442.            remove_from_list edi
  443.            pop ecx
  444.  
  445.            cmp [mem_block_list+ecx*4], edi
  446.            jne @f
  447.            mov [mem_block_list+ecx*4], edx
  448. @@:
  449.            cmp [mem_block_list+ecx*4], 0
  450.            jne @f
  451.            btr [mem_block_mask], ecx
  452. @@:
  453.            mov esi, [mem_block_list+eax*4]
  454.            mov [mem_block_list+eax*4], edi
  455.            mov [edi+list_next], esi
  456.            test esi, esi
  457.            jz @f
  458.            mov [esi+list_prev], edi
  459. @@:
  460.            bts [mem_block_mask], eax
  461. .m_eq:
  462.            xor eax, eax
  463.            mov [heap_mutex], eax
  464.            not eax
  465.            ret
  466. .insert:
  467.            remove_from_used esi
  468.  
  469.            mov eax, [esi+block_size]
  470.            calc_index eax
  471.  
  472.            mov edi, [mem_block_list+eax*4]
  473.            mov [mem_block_list+eax*4], esi
  474.            mov [esi+list_next], edi
  475.            test edi, edi
  476.            jz @f
  477.            mov [edi+list_prev], esi
  478. @@:
  479.            bts [mem_block_mask], eax
  480.            mov [esi+block_flags],FREE_BLOCK
  481.            xor eax, eax
  482.            mov [heap_mutex], eax
  483.            not eax
  484.            ret
  485. .fail:
  486.            xor eax, eax
  487.            mov [heap_mutex], eax
  488.            ret
  489. endp
  490.  
  491. align 4
  492. proc kernel_alloc stdcall, size:dword
  493.            locals
  494.              lin_addr    dd ?
  495.              pages_count dd ?
  496.            endl
  497.  
  498.            mov eax, [size]
  499.            add eax, 4095
  500.            and eax, not 4095;
  501.            mov [size], eax
  502.            and eax, eax
  503.            jz .error
  504.            mov ebx, eax
  505.            shr ebx, 12
  506.            mov [pages_count], ebx
  507.  
  508.            stdcall alloc_kernel_space, eax
  509.            and eax, eax
  510.            jz .error
  511.            mov [lin_addr], eax
  512.  
  513.            mov ecx, [pages_count]
  514.            mov edx, eax
  515.            mov ebx, ecx
  516.  
  517.            shr ecx, 3
  518.            jz .next
  519.  
  520.            and ebx, not 7
  521.            push ebx
  522.            stdcall alloc_pages, ebx
  523.            pop ecx                   ; yes ecx!!!
  524.            and eax, eax
  525.            jz .error
  526.  
  527.            mov edi, eax
  528.            mov edx, [lin_addr]
  529. @@:
  530.            stdcall map_page,edx,edi,dword PG_SW
  531.            add edx, 0x1000
  532.            add edi, 0x1000
  533.            dec ecx
  534.            jnz @B
  535. .next:
  536.            mov ecx, [pages_count]
  537.            and ecx, 7
  538.            jz .end
  539.  
  540. @@:        push ecx
  541.            call alloc_page
  542.            pop ecx
  543.            test eax, eax
  544.            jz .error
  545.  
  546.            stdcall map_page,edx,eax,dword PG_SW
  547.            add edx, 0x1000
  548.            dec ecx
  549.            jnz @B
  550. .end:
  551.            mov eax, [lin_addr]
  552.            ret
  553. .error:
  554.            xor eax, eax
  555.            ret
  556. endp
  557.  
  558. align 4
  559. proc kernel_free stdcall, base:dword
  560.  
  561.            mov ebx, heap_mutex
  562.            call wait_mutex    ;ebx
  563.  
  564.            mov eax, [base]
  565.            mov esi, [mem_used_list]
  566. @@:
  567.            test esi, esi
  568.            jz .fail
  569.  
  570.            cmp [esi+block_base], eax
  571.            je .found
  572.            mov esi, [esi+list_next]
  573.            jmp @b
  574. .found:
  575.            cmp [esi+block_flags], USED_BLOCK
  576.            jne .fail
  577.  
  578.            and [heap_mutex], 0
  579.  
  580.            mov ecx, [esi+block_size];
  581.            shr ecx, 12
  582.            call release_pages   ;eax, ecx
  583.            stdcall free_kernel_space, [base]
  584.            ret
  585. .fail:
  586.            and [heap_mutex], 0
  587.            ret
  588. endp
  589.  
  590. restore block_next
  591. restore block_prev
  592. restore block_list
  593. restore block_base
  594. restore block_size
  595. restore block_flags
  596.  
  597. ;;;;;;;;;;;;;;      USER     ;;;;;;;;;;;;;;;;;
  598.  
  599. HEAP_TOP  equ 0x5FC00000
  600.  
  601. align 4
  602. proc init_heap
  603.  
  604.            mov ebx,[CURRENT_TASK]
  605.            shl ebx,8
  606.            mov eax, [PROC_BASE+APPDATA.heap_top+ebx]
  607.            test eax, eax
  608.            jz @F
  609.            sub eax,[PROC_BASE+APPDATA.heap_base+ebx]
  610.            sub eax, 4096
  611.            ret
  612. @@:
  613.            mov esi, [PROC_BASE+APPDATA.mem_size+ebx]
  614.            add esi, 4095
  615.            and esi, not 4095
  616.            mov eax, HEAP_TOP
  617.            mov [PROC_BASE+APPDATA.heap_base+ebx], esi
  618.            mov [PROC_BASE+APPDATA.heap_top+ebx], eax
  619.  
  620.            sub eax, esi
  621.            add esi, new_app_base
  622.            shr esi, 10
  623.            mov ecx, eax
  624.            sub eax, 4096
  625.            or ecx, FREE_BLOCK
  626.            mov [pages_tab+esi], ecx
  627.            ret
  628. .exit:
  629.            xor eax, eax
  630.            ret
  631. endp
  632.  
  633. align 4
  634. proc user_alloc stdcall, alloc_size:dword
  635.  
  636.            mov ecx, [alloc_size]
  637.            add ecx, (4095+4096)
  638.            and ecx, not 4095
  639.  
  640.            mov ebx, [CURRENT_TASK]
  641.            shl ebx, 8
  642.            mov esi, dword [ebx+PROC_BASE+APPDATA.heap_base]; heap_base
  643.            mov edi, dword [ebx+PROC_BASE+APPDATA.heap_top]; heap_top
  644.            add esi, new_app_base
  645.            add edi, new_app_base
  646. l_0:
  647.            cmp esi, edi
  648.            jae m_exit
  649.  
  650.            mov ebx, esi
  651.            shr ebx, 12
  652.            mov eax, [pages_tab+ebx*4]
  653.            test eax, FREE_BLOCK
  654.            jz test_used
  655.            and eax, 0xFFFFF000
  656.            cmp eax, ecx    ;alloc_size
  657.            jb  m_next
  658.            jz  @f
  659.  
  660.            mov edx, esi
  661.            add edx, ecx
  662.            sub eax, ecx;
  663.            or eax, FREE_BLOCK
  664.            shr edx, 12
  665.            mov [pages_tab+edx*4], eax
  666.  
  667. @@:
  668.            or ecx, USED_BLOCK
  669.            mov [pages_tab+ebx*4], ecx
  670.            shr ecx, 12
  671.            dec ecx
  672.            inc ebx
  673. @@:
  674.            mov dword [pages_tab+ebx*4], 2
  675.            inc ebx
  676.            dec ecx
  677.            jnz @B
  678.  
  679.            mov eax, esi
  680.            add eax, 4096
  681.            sub eax, new_app_base
  682.            ret
  683. m_next:
  684.            add esi, eax
  685.            jmp l_0
  686. test_used:
  687.            test eax, USED_BLOCK
  688.            jz m_exit
  689.  
  690.            and eax, 0xFFFFF000
  691.            add esi, eax
  692.            jmp l_0
  693. m_exit:
  694.            xor eax, eax
  695.            ret
  696. endp
  697.  
  698. align 4
  699. proc user_free stdcall, base:dword
  700.  
  701.            mov esi, [base]
  702.            test esi, esi
  703.            jz .exit
  704.  
  705.            sub esi, 4096
  706.            shr esi, 12
  707.            mov eax, [pages_tab+esi*4]
  708.            test eax, USED_BLOCK
  709.            jz .not_used
  710.  
  711.            and eax, not 4095
  712.            mov ecx, eax
  713.            or eax, FREE_BLOCK
  714.            mov [pages_tab+esi*4], eax
  715.            inc esi
  716.            sub ecx, 4096
  717.            shr ecx, 12
  718. .release:
  719.            xor eax, eax
  720.            xchg eax, [pages_tab+esi*4]
  721.            test eax, 1
  722.            jz @F
  723.            call free_page
  724. @@:
  725.            inc esi
  726.            dec ecx
  727.            jnz .release
  728. .not_used:
  729.            mov ebx, [CURRENT_TASK]
  730.            shl ebx, 8
  731.            mov esi, dword [ebx+PROC_BASE+APPDATA.heap_base]; heap_base
  732.            mov edi, dword [ebx+PROC_BASE+APPDATA.heap_top]; heap_top
  733.            add esi, new_app_base
  734.            add edi, new_app_base
  735.            shr esi, 12
  736.            shr edi, 12
  737. @@:
  738.            mov eax, [pages_tab+esi*4]
  739.            test eax, USED_BLOCK
  740.            jz .test_free
  741.            shr eax, 12
  742.            add esi, eax
  743.            jmp @B
  744. .test_free:
  745.            test eax, FREE_BLOCK
  746.            jz .err
  747.            mov edx, eax
  748.            shr edx, 12
  749.            add edx, esi
  750.            cmp edx, edi
  751.            jae .exit
  752.  
  753.            mov ebx, [pages_tab+edx*4]
  754.            test ebx, USED_BLOCK
  755.            jz .next_free
  756.  
  757.            shr ebx, 12
  758.            add edx, ebx
  759.            mov esi, edx
  760.            jmp @B
  761. .next_free:
  762.            test ebx, FREE_BLOCK
  763.            jz .err
  764.            and dword [pages_tab+edx*4], 0
  765.            add eax, ebx
  766.            and eax, not 4095
  767.            or eax, FREE_BLOCK
  768.            mov [pages_tab+esi*4], eax
  769.            jmp @B
  770. .exit:
  771.            xor eax, eax
  772.            inc eax
  773.            ret
  774. .err:
  775.            xor eax, eax
  776.            ret
  777. endp
  778.  
  779. if 0
  780. align 4
  781. proc alloc_dll
  782.            pushf
  783.            cli
  784.            bsf eax, [dll_map]
  785.            jnz .find
  786.            popf
  787.            xor eax, eax
  788.            ret
  789. .find:
  790.            btr [dll_map], eax
  791.            popf
  792.            shl eax, 5
  793.            add eax, dll_tab
  794.            ret
  795. endp
  796.  
  797. align 4
  798. proc alloc_service
  799.            pushf
  800.            cli
  801.            bsf eax, [srv_map]
  802.            jnz .find
  803.            popf
  804.            xor eax, eax
  805.            ret
  806. .find:
  807.            btr [srv_map], eax
  808.            popf
  809.            shl eax,0x02
  810.            lea eax,[srv_tab+eax+eax*8]   ;srv_tab+eax*36
  811.            ret
  812. endp
  813.  
  814. end if
  815.