Subversion Repositories Kolibri OS

Rev

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

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