Subversion Repositories Kolibri OS

Rev

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