Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 1615 $
  9.  
  10.  
  11. struc MEM_BLOCK
  12. {  .next_block  dd ?
  13.    .prev_block  dd ? ;+4
  14.    .list_fd     dd ? ;+8
  15.    .list_bk     dd ? ;+12
  16.    .base        dd ? ;+16
  17.    .size        dd ? ;+20
  18.    .flags       dd ? ;+24
  19.    .handle      dd ? ;+28
  20. }
  21.  
  22. MEM_LIST_OFFSET equ  8
  23. FREE_BLOCK      equ  4
  24. USED_BLOCK      equ  8
  25. DONT_FREE_BLOCK equ  10h
  26.  
  27. virtual at 0
  28.   MEM_BLOCK MEM_BLOCK
  29. end virtual
  30.  
  31. MEM_BLOCK_SIZE equ 8*4
  32.  
  33. block_next   equ MEM_BLOCK.next_block
  34. block_prev   equ MEM_BLOCK.prev_block
  35. list_fd      equ MEM_BLOCK.list_fd
  36. list_bk      equ MEM_BLOCK.list_bk
  37. block_base   equ MEM_BLOCK.base
  38. block_size   equ MEM_BLOCK.size
  39. block_flags  equ MEM_BLOCK.flags
  40.  
  41. macro calc_index op
  42. {          shr op, 12
  43.            dec op
  44.            cmp op, 63
  45.            jna @f
  46.            mov op, 63
  47. @@:
  48. }
  49.  
  50. macro remove_from_list op
  51. {          mov edx, [op+list_fd]
  52.            mov ecx, [op+list_bk]
  53.            test edx, edx
  54.            jz @f
  55.            mov [edx+list_bk], ecx
  56. @@:
  57.            test ecx, ecx
  58.            jz @f
  59.            mov [ecx+list_fd], edx
  60. @@:
  61.            mov [op+list_fd],0
  62.            mov [op+list_bk],0
  63. }
  64.  
  65. macro remove_from_free op
  66. {
  67.            remove_from_list op
  68.  
  69.            mov eax, [op+block_size]
  70.            calc_index eax
  71.            cmp [mem_block_list+eax*4], op
  72.            jne @f
  73.            mov [mem_block_list+eax*4], edx
  74. @@:
  75.            cmp [mem_block_list+eax*4], 0
  76.            jne @f
  77.            btr [mem_block_mask], eax
  78. @@:
  79. }
  80.  
  81. macro remove_from_used op
  82. {
  83.            mov edx, [op+list_fd]
  84.            mov ecx, [op+list_bk]
  85.            mov [edx+list_bk], ecx
  86.            mov [ecx+list_fd], edx
  87.            mov [op+list_fd], 0
  88.            mov [op+list_bk], 0
  89. }
  90.  
  91. align 4
  92. proc init_kernel_heap
  93.  
  94.            mov ecx, 64
  95.            mov edi, mem_block_list
  96.            xor eax, eax
  97.            cld
  98.            rep stosd
  99.  
  100.            mov ecx, 512/4
  101.            mov edi, mem_block_map
  102.            not eax
  103.            rep stosd
  104.  
  105.            mov [mem_block_start], mem_block_map
  106.            mov [mem_block_end], mem_block_map+512
  107.            mov [mem_block_arr], HEAP_BASE
  108.  
  109.            mov eax, mem_used.fd-MEM_LIST_OFFSET
  110.            mov [mem_used.fd], eax
  111.            mov [mem_used.bk], eax
  112.  
  113.            stdcall alloc_pages, dword 32
  114.            mov ecx, 32
  115.            mov edx, eax
  116.            mov edi, HEAP_BASE
  117. .l1:
  118.            stdcall map_page,edi,edx,PG_SW
  119.            add edi, 0x1000
  120.            add edx, 0x1000
  121.            dec ecx
  122.            jnz .l1
  123.  
  124.            mov edi, HEAP_BASE
  125.            mov ebx, HEAP_BASE+MEM_BLOCK_SIZE
  126.            xor eax, eax
  127.            mov [edi+block_next], ebx
  128.            mov [edi+block_prev], eax
  129.            mov [edi+list_fd], eax
  130.            mov [edi+list_bk], eax
  131.            mov [edi+block_base], HEAP_BASE
  132.            mov [edi+block_size], 4096*MEM_BLOCK_SIZE
  133.            mov [edi+block_flags], USED_BLOCK
  134.  
  135.            mov [ebx+block_next], eax
  136.            mov [ebx+block_prev], eax
  137.            mov [ebx+list_fd], eax
  138.            mov [ebx+list_bk], eax
  139.            mov [ebx+block_base], HEAP_BASE+4096*MEM_BLOCK_SIZE
  140.  
  141.            mov ecx, [pg_data.kernel_pages]
  142.            shl ecx, 12
  143.            sub ecx, HEAP_BASE-OS_BASE+4096*MEM_BLOCK_SIZE
  144.            mov [heap_size], ecx
  145.            mov [heap_free], ecx
  146.            mov [ebx+block_size], ecx
  147.            mov [ebx+block_flags], FREE_BLOCK
  148.  
  149.            mov [mem_block_mask], eax
  150.            mov [mem_block_mask+4],0x80000000
  151.  
  152.            mov [mem_block_list+63*4], ebx
  153.            mov byte [mem_block_map], 0xFC
  154.            and [heap_mutex], 0
  155.            mov [heap_blocks], 4095
  156.            mov [free_blocks], 4094
  157.            ret
  158. endp
  159.  
  160. ; param
  161. ;  eax= required size
  162. ;
  163. ; retval
  164. ;  edi= memory block descriptor
  165. ;  ebx= descriptor index
  166.  
  167. align 4
  168. get_small_block:
  169.            mov ecx, eax
  170.            shr ecx, 12
  171.            dec ecx
  172.            cmp ecx, 63
  173.            jle .get_index
  174.            mov ecx, 63
  175. .get_index:
  176.            lea esi, [mem_block_mask]
  177.            xor ebx, ebx
  178.            or edx, -1
  179.  
  180.            cmp ecx, 32
  181.            jb .bit_test
  182.  
  183.            sub ecx, 32
  184.            add ebx, 32
  185.            add esi, 4
  186. .bit_test:
  187.            shl edx, cl
  188.            and edx, [esi]
  189. .find:
  190.            bsf edi, edx
  191.            jz .high_mask
  192.            add ebx, edi
  193.            mov edi, [mem_block_list+ebx*4]
  194. .check_size:
  195.            cmp eax, [edi+block_size]
  196.            ja .next
  197.            ret
  198.  
  199. .high_mask:
  200.            add esi, 4
  201.            cmp esi, mem_block_mask+8
  202.            jae .err
  203.            add ebx, 32
  204.            mov edx, [esi]
  205.            jmp .find
  206. .next:
  207.            mov edi, [edi+list_fd]
  208.            test edi, edi
  209.            jnz .check_size
  210. .err:
  211.            xor edi, edi
  212.            ret
  213.  
  214. align 4
  215. alloc_mem_block:
  216.  
  217.            mov ebx, [mem_block_start]
  218.            mov ecx, [mem_block_end]
  219. .l1:
  220.            bsf eax,[ebx];
  221.            jnz found
  222.            add ebx,4
  223.            cmp ebx, ecx
  224.            jb .l1
  225.            xor eax,eax
  226.            ret
  227.  
  228. found:
  229.            btr [ebx], eax
  230.            mov [mem_block_start],ebx
  231.            sub ebx, mem_block_map
  232.            lea eax,[eax+ebx*8]
  233.            shl eax, 5
  234.            add eax, [mem_block_arr]
  235.            dec [free_blocks]
  236.            ret
  237. align 4
  238. free_mem_block:
  239.            mov dword [eax], 0
  240.            mov dword [eax+4], 0
  241.            mov dword [eax+8], 0
  242.            mov dword [eax+12], 0
  243.            mov dword [eax+16], 0
  244. ;           mov dword [eax+20], 0
  245.            mov dword [eax+24], 0
  246.            mov dword [eax+28], 0
  247.  
  248.            sub eax, [mem_block_arr]
  249.            shr eax, 5
  250.  
  251.            mov ebx, mem_block_map
  252.            bts [ebx], eax
  253.            inc [free_blocks]
  254.            shr eax, 3
  255.            and eax, not 3
  256.            add eax, ebx
  257.            cmp [mem_block_start], eax
  258.            ja @f
  259.            ret
  260. @@:
  261.            mov [mem_block_start], eax
  262.            ret
  263. .err:
  264.            xor eax, eax
  265.            ret
  266.  
  267. align 4
  268. proc alloc_kernel_space stdcall, size:dword
  269.            local block_ind:DWORD
  270.  
  271.            push ebx
  272.            push esi
  273.            push edi
  274.  
  275.            mov eax, [size]
  276.            add eax, 4095
  277.            and eax, not 4095
  278.            mov [size], eax
  279.  
  280.            mov ebx, heap_mutex
  281.            call wait_mutex    ;ebx
  282.  
  283.            cmp eax, [heap_free]
  284.            ja .error
  285.  
  286.            call get_small_block ; eax
  287.            test edi, edi
  288.            jz .error
  289.  
  290.            cmp [edi+block_flags], FREE_BLOCK
  291.            jne .error
  292.  
  293.            mov [block_ind], ebx   ;index of allocated block
  294.  
  295.            mov eax, [edi+block_size]
  296.            cmp eax, [size]
  297.            je .m_eq_size
  298.  
  299.            call alloc_mem_block
  300.            and eax, eax
  301.            jz .error
  302.  
  303.            mov esi, eax           ;esi - splitted block
  304.  
  305.            mov [esi+block_next], edi
  306.            mov eax, [edi+block_prev]
  307.            mov [esi+block_prev], eax
  308.            mov [edi+block_prev], esi
  309.            mov [esi+list_fd], 0
  310.            mov [esi+list_bk], 0
  311.            and eax, eax
  312.            jz @f
  313.            mov [eax+block_next], esi
  314. @@:
  315.            mov ebx, [edi+block_base]
  316.            mov [esi+block_base], ebx
  317.            mov edx, [size]
  318.            mov [esi+block_size], edx
  319.            add [edi+block_base], edx
  320.            sub [edi+block_size], edx
  321.  
  322.            mov eax, [edi+block_size]
  323.            shr eax, 12
  324.            sub eax, 1
  325.            cmp eax, 63
  326.            jna @f
  327.            mov eax, 63
  328. @@:
  329.            cmp eax, [block_ind]
  330.            je .m_eq_ind
  331.  
  332.            remove_from_list edi
  333.  
  334.            mov ecx, [block_ind]
  335.            mov [mem_block_list+ecx*4], edx
  336.  
  337.            test edx, edx
  338.            jnz @f
  339.            btr [mem_block_mask], ecx
  340. @@:
  341.            mov edx, [mem_block_list+eax*4]
  342.            mov [edi+list_fd], edx
  343.            test edx, edx
  344.            jz @f
  345.            mov [edx+list_bk], edi
  346. @@:
  347.            mov [mem_block_list+eax*4], edi
  348.            bts [mem_block_mask], eax
  349. .m_eq_ind:
  350.            mov ecx, mem_used.fd-MEM_LIST_OFFSET
  351.            mov edx, [ecx+list_fd]
  352.            mov [esi+list_fd], edx
  353.            mov [esi+list_bk], ecx
  354.            mov [ecx+list_fd], esi
  355.            mov [edx+list_bk], esi
  356.  
  357.            mov [esi+block_flags], USED_BLOCK
  358.            mov eax, [esi+block_base]
  359.            mov ebx, [size]
  360.            sub [heap_free], ebx
  361.            and [heap_mutex], 0
  362.            pop edi
  363.            pop esi
  364.            pop ebx
  365.            ret
  366. .m_eq_size:
  367.            remove_from_list edi
  368.            mov [mem_block_list+ebx*4], edx
  369.            and edx, edx
  370.            jnz @f
  371.            btr [mem_block_mask], ebx
  372. @@:
  373.            mov ecx, mem_used.fd-MEM_LIST_OFFSET
  374.            mov edx, [ecx+list_fd]
  375.            mov [edi+list_fd], edx
  376.            mov [edi+list_bk], ecx
  377.            mov [ecx+list_fd], edi
  378.            mov [edx+list_bk], edi
  379.  
  380.            mov [edi+block_flags], USED_BLOCK
  381.            mov eax, [edi+block_base]
  382.            mov ebx, [size]
  383.            sub [heap_free], ebx
  384.            and [heap_mutex], 0
  385.            pop edi
  386.            pop esi
  387.            pop ebx
  388.            ret
  389. .error:
  390.            xor eax, eax
  391.            mov [heap_mutex], eax
  392.            pop edi
  393.            pop esi
  394.            pop ebx
  395.            ret
  396. endp
  397.  
  398. align 4
  399. proc free_kernel_space stdcall uses ebx ecx edx esi edi, base:dword
  400.            push ebx
  401.            push esi
  402.            push edi
  403.            mov ebx, heap_mutex
  404.            call wait_mutex    ;ebx
  405.  
  406.            mov eax, [base]
  407.            mov esi, [mem_used.fd]
  408. @@:
  409.            cmp esi, mem_used.fd-MEM_LIST_OFFSET
  410.            je .fail
  411.  
  412.            cmp [esi+block_base], eax
  413.            je .found
  414.            mov esi, [esi+list_fd]
  415.            jmp @b
  416. .found:
  417.            cmp [esi+block_flags], USED_BLOCK
  418.            jne .fail
  419.  
  420.            mov eax, [esi+block_size]
  421.            add [heap_free], eax
  422.  
  423.            mov edi, [esi+block_next]
  424.            test edi, edi
  425.            jz .prev
  426.  
  427.            cmp [edi+block_flags], FREE_BLOCK
  428.            jne .prev
  429.  
  430.            remove_from_free edi
  431.  
  432.            mov edx, [edi+block_next]
  433.            mov [esi+block_next], edx
  434.            test edx, edx
  435.            jz @f
  436.  
  437.            mov [edx+block_prev], esi
  438. @@:
  439.            mov ecx, [edi+block_size]
  440.            add [esi+block_size], ecx
  441.  
  442.            mov eax, edi
  443.            call free_mem_block
  444. .prev:
  445.            mov edi, [esi+block_prev]
  446.            test edi, edi
  447.            jz .insert
  448.  
  449.            cmp [edi+block_flags], FREE_BLOCK
  450.            jne .insert
  451.  
  452.            remove_from_used esi
  453.  
  454.            mov edx, [esi+block_next]
  455.            mov [edi+block_next], edx
  456.            test edx, edx
  457.            jz @f
  458.            mov [edx+block_prev], edi
  459. @@:
  460.            mov eax, esi
  461.            call free_mem_block
  462.  
  463.            mov ecx, [edi+block_size]
  464.            mov eax, [esi+block_size]
  465.            add eax, ecx
  466.            mov [edi+block_size], eax
  467.  
  468.            calc_index eax
  469.            calc_index ecx
  470.            cmp eax, ecx
  471.            je .m_eq
  472.  
  473.            push ecx
  474.            remove_from_list edi
  475.            pop ecx
  476.  
  477.            cmp [mem_block_list+ecx*4], edi
  478.            jne @f
  479.            mov [mem_block_list+ecx*4], edx
  480. @@:
  481.            cmp [mem_block_list+ecx*4], 0
  482.            jne @f
  483.            btr [mem_block_mask], ecx
  484. @@:
  485.            mov esi, [mem_block_list+eax*4]
  486.            mov [mem_block_list+eax*4], edi
  487.            mov [edi+list_fd], esi
  488.            test esi, esi
  489.            jz @f
  490.            mov [esi+list_bk], edi
  491. @@:
  492.            bts [mem_block_mask], eax
  493. .m_eq:
  494.            xor eax, eax
  495.            mov [heap_mutex], eax
  496.            dec eax
  497.            pop edi
  498.            pop esi
  499.            pop ebx
  500.            ret
  501. .insert:
  502.            remove_from_used esi
  503.  
  504.            mov eax, [esi+block_size]
  505.            calc_index eax
  506.  
  507.            mov edi, [mem_block_list+eax*4]
  508.            mov [mem_block_list+eax*4], esi
  509.            mov [esi+list_fd], edi
  510.            test edi, edi
  511.            jz @f
  512.            mov [edi+list_bk], esi
  513. @@:
  514.            bts [mem_block_mask], eax
  515.            mov [esi+block_flags],FREE_BLOCK
  516.            xor eax, eax
  517.            mov [heap_mutex], eax
  518.            dec eax
  519.            pop edi
  520.            pop esi
  521.            pop ebx
  522.            ret
  523. .fail:
  524.            xor eax, eax
  525.            mov [heap_mutex], eax
  526.            pop edi
  527.            pop esi
  528.            pop ebx
  529.            ret
  530. endp
  531.  
  532. align 4
  533. proc kernel_alloc stdcall, size:dword
  534.            locals
  535.              lin_addr    dd ?
  536.              pages_count dd ?
  537.            endl
  538.  
  539.            push ebx
  540.            push edi
  541.  
  542.            mov eax, [size]
  543.            add eax, 4095
  544.            and eax, not 4095;
  545.            mov [size], eax
  546.            and eax, eax
  547.            jz .err
  548.            mov ebx, eax
  549.            shr ebx, 12
  550.            mov [pages_count], ebx
  551.  
  552.            stdcall alloc_kernel_space, eax
  553.            test eax, eax
  554.            jz .err
  555.            mov [lin_addr], eax
  556.  
  557.            mov ecx, [pages_count]
  558.            mov edx, eax
  559.            mov ebx, ecx
  560.  
  561.            shr ecx, 3
  562.            jz .next
  563.  
  564.            and ebx, not 7
  565.            push ebx
  566.            stdcall alloc_pages, ebx
  567.            pop ecx                   ; yes ecx!!!
  568.            and eax, eax
  569.            jz .err
  570.  
  571.            mov edi, eax
  572.            mov edx, [lin_addr]
  573. @@:
  574.            stdcall map_page,edx,edi,dword PG_SW
  575.            add edx, 0x1000
  576.            add edi, 0x1000
  577.            dec ecx
  578.            jnz @B
  579. .next:
  580.            mov ecx, [pages_count]
  581.            and ecx, 7
  582.            jz .end
  583. @@:
  584.            push ecx
  585.            call alloc_page
  586.            pop ecx
  587.            test eax, eax
  588.            jz .err
  589.  
  590.            stdcall map_page,edx,eax,dword PG_SW
  591.            add edx, 0x1000
  592.            dec ecx
  593.            jnz @B
  594. .end:
  595.            mov eax, [lin_addr]
  596.            pop edi
  597.            pop ebx
  598.            ret
  599. .err:
  600.            xor eax, eax
  601.            pop edi
  602.            pop ebx
  603.            ret
  604. endp
  605.  
  606. align 4
  607. proc kernel_free stdcall, base:dword
  608.            push ebx esi
  609.  
  610.            mov ebx, heap_mutex
  611.            call wait_mutex    ;ebx
  612.  
  613.            mov eax, [base]
  614.            mov esi, [mem_used.fd]
  615. @@:
  616.            cmp esi, mem_used.fd-MEM_LIST_OFFSET
  617.            je .fail
  618.  
  619.            cmp [esi+block_base], eax
  620.            je .found
  621.            mov esi, [esi+list_fd]
  622.            jmp @b
  623. .found:
  624.            cmp [esi+block_flags], USED_BLOCK
  625.            jne .fail
  626.  
  627.            and [heap_mutex], 0
  628.  
  629.            push ecx
  630.            mov ecx, [esi+block_size];
  631.            shr ecx, 12
  632.            call release_pages   ;eax, ecx
  633.            pop ecx
  634.            stdcall free_kernel_space, [base]
  635.            pop esi ebx
  636.            ret
  637. .fail:
  638.            xor eax, eax
  639.            mov [heap_mutex], eax
  640.            pop esi ebx
  641.            ret
  642. endp
  643.  
  644. restore block_next
  645. restore block_prev
  646. restore block_list
  647. restore block_base
  648. restore block_size
  649. restore block_flags
  650.  
  651. ;;;;;;;;;;;;;;      USER     ;;;;;;;;;;;;;;;;;
  652.  
  653. HEAP_TOP  equ 0x5FC00000
  654.  
  655. align 4
  656. proc init_heap
  657.  
  658.            mov ebx,[current_slot]
  659.            mov eax, [ebx+APPDATA.heap_top]
  660.            test eax, eax
  661.            jz @F
  662.            sub eax,[ebx+APPDATA.heap_base]
  663.            sub eax, 4096
  664.            ret
  665. @@:
  666.            mov esi, [ebx+APPDATA.mem_size]
  667.            add esi, 4095
  668.            and esi, not 4095
  669.            mov [ebx+APPDATA.mem_size], esi
  670.            mov eax, HEAP_TOP
  671.            mov [ebx+APPDATA.heap_base], esi
  672.            mov [ebx+APPDATA.heap_top], eax
  673.  
  674.            sub eax, esi
  675.            shr esi, 10
  676.            mov ecx, eax
  677.            sub eax, 4096
  678.            or ecx, FREE_BLOCK
  679.            mov [page_tabs+esi], ecx
  680.            ret
  681. endp
  682.  
  683. align 4
  684. proc user_alloc stdcall, alloc_size:dword
  685.  
  686.            push ebx
  687.            push esi
  688.            push edi
  689.  
  690.            mov ecx, [alloc_size]
  691.            add ecx, (4095+4096)
  692.            and ecx, not 4095
  693.  
  694.            mov ebx, [current_slot]
  695.            mov esi, dword [ebx+APPDATA.heap_base]  ; heap_base
  696.            mov edi, dword [ebx+APPDATA.heap_top]   ; heap_top
  697. l_0:
  698.            cmp esi, edi
  699.            jae m_exit
  700.  
  701.            mov ebx, esi
  702.            shr ebx, 12
  703.            mov eax, [page_tabs+ebx*4]
  704.            test al, FREE_BLOCK
  705.            jz test_used
  706.            and eax, 0xFFFFF000
  707.            cmp eax, ecx    ;alloc_size
  708.            jb  m_next
  709.            jz  @f
  710.  
  711.            lea edx, [esi+ecx]
  712.            sub eax, ecx
  713.            or al, FREE_BLOCK
  714.            shr edx, 12
  715.            mov [page_tabs+edx*4], eax
  716. @@:
  717.            or ecx, USED_BLOCK
  718.            mov [page_tabs+ebx*4], ecx
  719.            shr ecx, 12
  720.            inc ebx
  721.            dec ecx
  722.            jz  .no
  723. @@:
  724.            mov dword [page_tabs+ebx*4], 2
  725.            inc ebx
  726.            dec ecx
  727.            jnz @B
  728. .no:
  729.  
  730.            mov     edx, [current_slot]
  731.            mov     ebx, [alloc_size]
  732.            add     ebx, 0xFFF
  733.            and     ebx, not 0xFFF
  734.            add     ebx, [edx+APPDATA.mem_size]
  735.            call    update_mem_size
  736.  
  737.            lea eax, [esi+4096]
  738.  
  739.            pop edi
  740.            pop esi
  741.            pop ebx
  742.            ret
  743. test_used:
  744.            test al, USED_BLOCK
  745.            jz m_exit
  746.  
  747.            and eax, 0xFFFFF000
  748. m_next:
  749.            add esi, eax
  750.            jmp l_0
  751. m_exit:
  752.            xor eax, eax
  753.            pop edi
  754.            pop esi
  755.            pop ebx
  756.            ret
  757. endp
  758.  
  759. align 4
  760. proc user_alloc_at stdcall, address:dword, alloc_size:dword
  761.  
  762.            push ebx
  763.            push esi
  764.            push edi
  765.  
  766.            mov ebx, [current_slot]
  767.            mov edx, [address]
  768.            and edx, not 0xFFF
  769.            mov [address], edx
  770.            sub edx, 0x1000
  771.            jb  .error
  772.            mov esi, [ebx+APPDATA.heap_base]
  773.            mov edi, [ebx+APPDATA.heap_top]
  774.            cmp edx, esi
  775.            jb  .error
  776. .scan:
  777.            cmp esi, edi
  778.            jae .error
  779.            mov ebx, esi
  780.            shr ebx, 12
  781.            mov eax, [page_tabs+ebx*4]
  782.            mov ecx, eax
  783.            and ecx, 0xFFFFF000
  784.            add ecx, esi
  785.            cmp edx, ecx
  786.            jb  .found
  787.            mov esi, ecx
  788.            jmp .scan
  789. .error:
  790.            xor eax, eax
  791.            pop edi
  792.            pop esi
  793.            pop ebx
  794.            ret
  795. .found:
  796.            test al, FREE_BLOCK
  797.            jz  .error
  798.            mov eax, ecx
  799.            sub eax, edx
  800.            sub eax, 0x1000
  801.            cmp eax, [alloc_size]
  802.            jb  .error
  803.  
  804. ; Here we have 1 big free block which includes requested area.
  805. ; In general, 3 other blocks must be created instead:
  806. ; free at [esi, edx);
  807. ; busy at [edx, edx+0x1000+ALIGN_UP(alloc_size,0x1000));
  808. ; free at [edx+0x1000+ALIGN_UP(alloc_size,0x1000), ecx)
  809. ; First or third block (or both) may be absent.
  810.            mov eax, edx
  811.            sub eax, esi
  812.            jz  .nofirst
  813.            or  al, FREE_BLOCK
  814.            mov [page_tabs+ebx*4], eax
  815. .nofirst:
  816.            mov eax, [alloc_size]
  817.            add eax, 0x1FFF
  818.            and eax, not 0xFFF
  819.            mov ebx, edx
  820.            add edx, eax
  821.            shr ebx, 12
  822.            or  al, USED_BLOCK
  823.            mov [page_tabs+ebx*4], eax
  824.            shr eax, 12
  825.            dec eax
  826.            jz  .second_nofill
  827.            inc ebx
  828. .fill:
  829.            mov dword [page_tabs+ebx*4], 2
  830.            inc ebx
  831.            dec eax
  832.            jnz .fill
  833. .second_nofill:
  834.            sub ecx, edx
  835.            jz  .nothird
  836.            or  cl, FREE_BLOCK
  837.            mov [page_tabs+ebx*4], ecx
  838. .nothird:
  839.  
  840.            mov     edx, [current_slot]
  841.            mov     ebx, [alloc_size]
  842.            add     ebx, 0xFFF
  843.            and     ebx, not 0xFFF
  844.            add     ebx, [edx+APPDATA.mem_size]
  845.            call    update_mem_size
  846.  
  847.            mov eax, [address]
  848.  
  849.            pop edi
  850.            pop esi
  851.            pop ebx
  852.            ret
  853. endp
  854.  
  855. align 4
  856. proc user_free stdcall, base:dword
  857.  
  858.            push esi
  859.  
  860.            mov esi, [base]
  861.            test esi, esi
  862.            jz .exit
  863.  
  864.            push ebx
  865.  
  866.            xor ebx, ebx
  867.            shr esi, 12
  868.            mov eax, [page_tabs+(esi-1)*4]
  869.            test al, USED_BLOCK
  870.            jz .cantfree
  871.            test al, DONT_FREE_BLOCK
  872.            jnz .cantfree
  873.  
  874.            and eax, not 4095
  875.            mov ecx, eax
  876.            or al, FREE_BLOCK
  877.            mov [page_tabs+(esi-1)*4], eax
  878.            sub ecx, 4096
  879.            mov ebx, ecx
  880.            shr ecx, 12
  881.            jz .released
  882. .release:
  883.            xor eax, eax
  884.            xchg eax, [page_tabs+esi*4]
  885.            test al, 1
  886.            jz @F
  887.            test eax, PG_SHARED
  888.            jnz @F
  889.            call free_page
  890.            mov eax, esi
  891.            shl eax, 12
  892.            invlpg [eax]
  893. @@:
  894.            inc esi
  895.            dec ecx
  896.            jnz .release
  897. .released:
  898.            push edi
  899.  
  900.            mov edx, [current_slot]
  901.            mov esi, dword [edx+APPDATA.heap_base]
  902.            mov edi, dword [edx+APPDATA.heap_top]
  903.            sub ebx, [edx+APPDATA.mem_size]
  904.            neg ebx
  905.            call update_mem_size
  906.            call user_normalize
  907.            pop edi
  908.            pop ebx
  909.            pop esi
  910.            ret
  911. .exit:
  912.            xor eax, eax
  913.            inc eax
  914.            pop esi
  915.            ret
  916. .cantfree:
  917.            xor eax, eax
  918.            pop ebx
  919.            pop esi
  920.            ret
  921. endp
  922.  
  923. user_normalize:
  924. ; in: esi=heap_base, edi=heap_top
  925. ; out: eax=0 <=> OK
  926. ; destroys: ebx,edx,esi,edi
  927.            shr esi, 12
  928.            shr edi, 12
  929. @@:
  930.            mov eax, [page_tabs+esi*4]
  931.            test al, USED_BLOCK
  932.            jz .test_free
  933.            shr eax, 12
  934.            add esi, eax
  935.            jmp @B
  936. .test_free:
  937.            test al, FREE_BLOCK
  938.            jz .err
  939.            mov edx, eax
  940.            shr edx, 12
  941.            add edx, esi
  942.            cmp edx, edi
  943.            jae .exit
  944.  
  945.            mov ebx, [page_tabs+edx*4]
  946.            test bl, USED_BLOCK
  947.            jz .next_free
  948.  
  949.            shr ebx, 12
  950.            add edx, ebx
  951.            mov esi, edx
  952.            jmp @B
  953. .next_free:
  954.            test bl, FREE_BLOCK
  955.            jz .err
  956.            and dword [page_tabs+edx*4], 0
  957.            add eax, ebx
  958.            and eax, not 4095
  959.            or eax, FREE_BLOCK
  960.            mov [page_tabs+esi*4], eax
  961.            jmp @B
  962. .exit:
  963.            xor eax, eax
  964.            inc eax
  965.            ret
  966. .err:
  967.            xor eax, eax
  968.            ret
  969.  
  970. user_realloc:
  971. ; in: eax = pointer, ebx = new size
  972. ; out: eax = new pointer or NULL
  973.         test    eax, eax
  974.         jnz     @f
  975. ; realloc(NULL,sz) - same as malloc(sz)
  976.         push    ebx
  977.         call    user_alloc
  978.         ret
  979. @@:
  980.         push    ecx edx
  981.         lea     ecx, [eax - 0x1000]
  982.         shr     ecx, 12
  983.         mov     edx, [page_tabs+ecx*4]
  984.         test    dl, USED_BLOCK
  985.         jnz     @f
  986. ; attempt to realloc invalid pointer
  987. .ret0:
  988.         pop     edx ecx
  989.         xor     eax, eax
  990.         ret
  991. @@:
  992.         test    dl, DONT_FREE_BLOCK
  993.         jnz     .ret0
  994.         add     ebx, 0x1FFF
  995.         shr     edx, 12
  996.         shr     ebx, 12
  997. ; edx = allocated size, ebx = new size
  998.         add     edx, ecx
  999.         add     ebx, ecx
  1000.         cmp     edx, ebx
  1001.         jb      .realloc_add
  1002. ; release part of allocated memory
  1003. .loop:
  1004.         cmp     edx, ebx
  1005.         jz      .release_done
  1006.         dec     edx
  1007.         xor     eax, eax
  1008.         xchg    eax, [page_tabs+edx*4]
  1009.         test    al, 1
  1010.         jz      .loop
  1011.         call    free_page
  1012.         mov     eax, edx
  1013.         shl     eax, 12
  1014.         invlpg  [eax]
  1015.         jmp     .loop
  1016. .release_done:
  1017.         sub     ebx, ecx
  1018.         cmp     ebx, 1
  1019.         jnz     .nofreeall
  1020.         mov     eax, [page_tabs+ecx*4]
  1021.         and     eax, not 0xFFF
  1022.         mov     edx, [current_slot]
  1023.         mov     ebx, [APPDATA.mem_size+edx]
  1024.         sub     ebx, eax
  1025.         add     ebx, 0x1000
  1026.         or      al, FREE_BLOCK
  1027.         mov     [page_tabs+ecx*4], eax
  1028.         push    esi edi
  1029.         mov     esi, [APPDATA.heap_base+edx]
  1030.         mov     edi, [APPDATA.heap_top+edx]
  1031.         call    update_mem_size
  1032.         call    user_normalize
  1033.         pop     edi esi
  1034.         jmp     .ret0   ; all freed
  1035. .nofreeall:
  1036.         sub     edx, ecx
  1037.         shl     ebx, 12
  1038.         or      ebx, USED_BLOCK
  1039.         xchg    [page_tabs+ecx*4], ebx
  1040.         shr     ebx, 12
  1041.         sub     ebx, edx
  1042.         push    ebx ecx edx
  1043.         mov     edx, [current_slot]
  1044.         shl     ebx, 12
  1045.         sub     ebx, [APPDATA.mem_size+edx]
  1046.         neg     ebx
  1047.         call    update_mem_size
  1048.         pop     edx ecx ebx
  1049.         lea     eax, [ecx+1]
  1050.         shl     eax, 12
  1051.         push    eax
  1052.         add     ecx, edx
  1053.         lea     edx, [ecx+ebx]
  1054.         shl     ebx, 12
  1055.         jz      .ret
  1056.         push    esi
  1057.         mov     esi, [current_slot]
  1058.         mov     esi, [APPDATA.heap_top+esi]
  1059.         shr     esi, 12
  1060. @@:
  1061.         cmp     edx, esi
  1062.         jae     .merge_done
  1063.         mov     eax, [page_tabs+edx*4]
  1064.         test    al, USED_BLOCK
  1065.         jnz     .merge_done
  1066.         and     dword [page_tabs+edx*4], 0
  1067.         shr     eax, 12
  1068.         add     edx, eax
  1069.         shl     eax, 12
  1070.         add     ebx, eax
  1071.         jmp     @b
  1072. .merge_done:
  1073.         pop     esi
  1074.         or      ebx, FREE_BLOCK
  1075.         mov     [page_tabs+ecx*4], ebx
  1076. .ret:
  1077.         pop     eax edx ecx
  1078.         ret
  1079. .realloc_add:
  1080. ; get some additional memory
  1081.         mov     eax, [current_slot]
  1082.         mov     eax, [APPDATA.heap_top+eax]
  1083.         shr     eax, 12
  1084.         cmp     edx, eax
  1085.         jae     .cant_inplace
  1086.         mov     eax, [page_tabs+edx*4]
  1087.         test    al, FREE_BLOCK
  1088.         jz      .cant_inplace
  1089.         shr     eax, 12
  1090.         add     eax, edx
  1091.         sub     eax, ebx
  1092.         jb      .cant_inplace
  1093.         jz      @f
  1094.         shl     eax, 12
  1095.         or      al, FREE_BLOCK
  1096.         mov     [page_tabs+ebx*4], eax
  1097. @@:
  1098.         mov     eax, ebx
  1099.         sub     eax, ecx
  1100.         shl     eax, 12
  1101.         or      al, USED_BLOCK
  1102.         mov     [page_tabs+ecx*4], eax
  1103.         lea     eax, [ecx+1]
  1104.         shl     eax, 12
  1105.         push    eax
  1106.         push    edi
  1107.         lea     edi, [page_tabs+edx*4]
  1108.         mov     eax, 2
  1109.         sub     ebx, edx
  1110.         mov     ecx, ebx
  1111.         cld
  1112.         rep     stosd
  1113.         pop     edi
  1114.         mov     edx, [current_slot]
  1115.         shl     ebx, 12
  1116.         add     ebx, [APPDATA.mem_size+edx]
  1117.         call    update_mem_size
  1118.         pop     eax edx ecx
  1119.         ret
  1120. .cant_inplace:
  1121.         push    esi edi
  1122.         mov     eax, [current_slot]
  1123.         mov     esi, [APPDATA.heap_base+eax]
  1124.         mov     edi, [APPDATA.heap_top+eax]
  1125.         shr     esi, 12
  1126.         shr     edi, 12
  1127.         sub     ebx, ecx
  1128. .find_place:
  1129.         cmp     esi, edi
  1130.         jae     .place_not_found
  1131.         mov     eax, [page_tabs+esi*4]
  1132.         test    al, FREE_BLOCK
  1133.         jz      .next_place
  1134.         shr     eax, 12
  1135.         cmp     eax, ebx
  1136.         jae     .place_found
  1137.         add     esi, eax
  1138.         jmp     .find_place
  1139. .next_place:
  1140.         shr     eax, 12
  1141.         add     esi, eax
  1142.         jmp     .find_place
  1143. .place_not_found:
  1144.         pop     edi esi
  1145.         jmp     .ret0
  1146. .place_found:
  1147.         sub     eax, ebx
  1148.         jz      @f
  1149.         push    esi
  1150.         add     esi, ebx
  1151.         shl     eax, 12
  1152.         or      al, FREE_BLOCK
  1153.         mov     [page_tabs+esi*4], eax
  1154.         pop     esi
  1155. @@:
  1156.         mov     eax, ebx
  1157.         shl     eax, 12
  1158.         or      al, USED_BLOCK
  1159.         mov     [page_tabs+esi*4], eax
  1160.         inc     esi
  1161.         mov     eax, esi
  1162.         shl     eax, 12
  1163.         push    eax
  1164.         mov     eax, [page_tabs+ecx*4]
  1165.         and     eax, not 0xFFF
  1166.         or      al, FREE_BLOCK
  1167.         sub     edx, ecx
  1168.         mov     [page_tabs+ecx*4], eax
  1169.         inc     ecx
  1170.         dec     ebx
  1171.         dec     edx
  1172.         jz      .no
  1173. @@:
  1174.         xor     eax, eax
  1175.         xchg    eax, [page_tabs+ecx*4]
  1176.         mov     [page_tabs+esi*4], eax
  1177.         mov     eax, ecx
  1178.         shl     eax, 12
  1179.         invlpg  [eax]
  1180.         inc     esi
  1181.         inc     ecx
  1182.         dec     ebx
  1183.         dec     edx
  1184.         jnz     @b
  1185. .no:
  1186.         push    ebx
  1187.         mov     edx, [current_slot]
  1188.         shl     ebx, 12
  1189.         add     ebx, [APPDATA.mem_size+edx]
  1190.         call    update_mem_size
  1191.         pop     ebx
  1192. @@:
  1193.         mov     dword [page_tabs+esi*4], 2
  1194.         inc     esi
  1195.         dec     ebx
  1196.         jnz     @b
  1197.         pop     eax edi esi edx ecx
  1198.         ret
  1199.  
  1200. if 0
  1201. align 4
  1202. proc alloc_dll
  1203.            pushf
  1204.            cli
  1205.            bsf eax, [dll_map]
  1206.            jnz .find
  1207.            popf
  1208.            xor eax, eax
  1209.            ret
  1210. .find:
  1211.            btr [dll_map], eax
  1212.            popf
  1213.            shl eax, 5
  1214.            add eax, dll_tab
  1215.            ret
  1216. endp
  1217.  
  1218. align 4
  1219. proc alloc_service
  1220.            pushf
  1221.            cli
  1222.            bsf eax, [srv_map]
  1223.            jnz .find
  1224.            popf
  1225.            xor eax, eax
  1226.            ret
  1227. .find:
  1228.            btr [srv_map], eax
  1229.            popf
  1230.            shl eax,0x02
  1231.            lea eax,[srv_tab+eax+eax*8]   ;srv_tab+eax*36
  1232.            ret
  1233. endp
  1234.  
  1235. end if
  1236.  
  1237.  
  1238. ;;;;;;;;;;;;;;      SHARED      ;;;;;;;;;;;;;;;;;
  1239.  
  1240.  
  1241. ; param
  1242. ;  eax= shm_map object
  1243.  
  1244. align 4
  1245. destroy_smap:
  1246.  
  1247.            pushfd
  1248.            cli
  1249.  
  1250.            push esi
  1251.            push edi
  1252.  
  1253.            mov edi, eax
  1254.            mov esi, [eax+SMAP.parent]
  1255.            test esi, esi
  1256.            jz .done
  1257.  
  1258.            lock dec [esi+SMEM.refcount]
  1259.            jnz .done
  1260.  
  1261.            mov ecx, [esi+SMEM.bk]
  1262.            mov edx, [esi+SMEM.fd]
  1263.  
  1264.            mov [ecx+SMEM.fd], edx
  1265.            mov [edx+SMEM.bk], ecx
  1266.  
  1267.            stdcall kernel_free, [esi+SMEM.base]
  1268.            mov eax, esi
  1269.            call free
  1270. .done:
  1271.            mov eax, edi
  1272.            call destroy_kernel_object
  1273.  
  1274.            pop edi
  1275.            pop esi
  1276.            popfd
  1277.  
  1278.            ret
  1279.  
  1280. E_NOTFOUND      equ  5
  1281. E_ACCESS        equ 10
  1282. E_NOMEM         equ 30
  1283. E_PARAM         equ 33
  1284.  
  1285. SHM_READ        equ 0
  1286. SHM_WRITE       equ 1
  1287.  
  1288. SHM_ACCESS_MASK equ 3
  1289.  
  1290. SHM_OPEN        equ (0 shl 2)
  1291. SHM_OPEN_ALWAYS equ (1 shl 2)
  1292. SHM_CREATE      equ (2 shl 2)
  1293.  
  1294. SHM_OPEN_MASK   equ (3 shl 2)
  1295.  
  1296. align 4
  1297. proc shmem_open stdcall name:dword, size:dword, access:dword
  1298.            locals
  1299.               action         dd ?
  1300.               owner_access   dd ?
  1301.               mapped         dd ?
  1302.            endl
  1303.  
  1304.            push ebx
  1305.            push esi
  1306.            push edi
  1307.  
  1308.            mov [mapped], 0
  1309.            mov [owner_access], 0
  1310.  
  1311.            pushfd                      ;mutex required
  1312.            cli
  1313.  
  1314.            mov eax, [access]
  1315.            and eax, SHM_OPEN_MASK
  1316.            mov [action], eax
  1317.  
  1318.            mov ebx, [name]
  1319.            test ebx, ebx
  1320.            mov edx, E_PARAM
  1321.            jz .fail
  1322.  
  1323.            mov esi, [shmem_list.fd]
  1324. align 4
  1325. @@:
  1326.            cmp esi, shmem_list
  1327.            je .not_found
  1328.  
  1329.            lea edx, [esi+SMEM.name] ; link , base, size
  1330.            stdcall strncmp, edx, ebx, 32
  1331.            test eax, eax
  1332.            je .found
  1333.  
  1334.            mov esi, [esi+SMEM.fd]
  1335.            jmp @B
  1336.  
  1337. .not_found:
  1338.            mov eax, [action]
  1339.  
  1340.            cmp eax, SHM_OPEN
  1341.            mov edx, E_NOTFOUND
  1342.            je .fail
  1343.  
  1344.            cmp eax, SHM_CREATE
  1345.            mov edx, E_PARAM
  1346.            je .create_shm
  1347.  
  1348.            cmp eax, SHM_OPEN_ALWAYS
  1349.            jne .fail
  1350.  
  1351. .create_shm:
  1352.  
  1353.            mov ecx, [size]
  1354.            test ecx, ecx
  1355.            jz .fail
  1356.  
  1357.            add ecx, 4095
  1358.            and ecx, -4096
  1359.            mov [size], ecx
  1360.  
  1361.            mov eax, SMEM.sizeof
  1362.            call malloc
  1363.            test eax, eax
  1364.            mov esi, eax
  1365.            mov edx, E_NOMEM
  1366.            jz .fail
  1367.  
  1368.            stdcall kernel_alloc, [size]
  1369.            test eax, eax
  1370.            mov [mapped], eax
  1371.            mov edx, E_NOMEM
  1372.            jz .cleanup
  1373.  
  1374.            mov ecx, [size]
  1375.            mov edx, [access]
  1376.            and edx, SHM_ACCESS_MASK
  1377.  
  1378.            mov [esi+SMEM.base], eax
  1379.            mov [esi+SMEM.size], ecx
  1380.            mov [esi+SMEM.access], edx
  1381.            mov [esi+SMEM.refcount], 0
  1382.            mov [esi+SMEM.name+28], 0
  1383.  
  1384.            lea eax, [esi+SMEM.name]
  1385.            stdcall strncpy, eax, [name], 31
  1386.  
  1387.            mov eax, [shmem_list.fd]
  1388.            mov [esi+SMEM.bk], shmem_list
  1389.            mov [esi+SMEM.fd], eax
  1390.  
  1391.            mov [eax+SMEM.bk], esi
  1392.            mov [shmem_list.fd], esi
  1393.  
  1394.            mov [action], SHM_OPEN
  1395.            mov [owner_access], SHM_WRITE
  1396.  
  1397. .found:
  1398.            mov eax, [action]
  1399.  
  1400.            cmp eax, SHM_CREATE
  1401.            mov edx, E_ACCESS
  1402.            je .exit
  1403.  
  1404.            cmp eax, SHM_OPEN
  1405.            mov edx, E_PARAM
  1406.            je .create_map
  1407.  
  1408.            cmp eax, SHM_OPEN_ALWAYS
  1409.            jne .fail
  1410.  
  1411. .create_map:
  1412.  
  1413.            mov eax, [access]
  1414.            and eax, SHM_ACCESS_MASK
  1415.            cmp eax, [esi+SMEM.access]
  1416.            mov [access], eax
  1417.            mov edx, E_ACCESS
  1418.            ja .fail
  1419.  
  1420.            mov ebx, [CURRENT_TASK]
  1421.            shl ebx, 5
  1422.            mov ebx, [CURRENT_TASK+ebx+4]
  1423.            mov eax, SMAP.sizeof
  1424.  
  1425.            call create_kernel_object
  1426.            test eax, eax
  1427.            mov edi, eax
  1428.            mov edx, E_NOMEM
  1429.            jz .fail
  1430.  
  1431.            inc [esi+SMEM.refcount]
  1432.  
  1433.            mov [edi+SMAP.magic], 'SMAP'
  1434.            mov [edi+SMAP.destroy], destroy_smap
  1435.            mov [edi+SMAP.parent], esi
  1436.            mov [edi+SMAP.base], 0
  1437.  
  1438.            stdcall user_alloc, [esi+SMEM.size]
  1439.            test eax, eax
  1440.            mov [mapped], eax
  1441.            mov edx, E_NOMEM
  1442.            jz .cleanup2
  1443.  
  1444.            mov [edi+SMAP.base], eax
  1445.  
  1446.            mov ecx, [esi+SMEM.size]
  1447.            mov [size], ecx
  1448.  
  1449.            shr ecx, 12
  1450.            shr eax, 10
  1451.  
  1452.            mov esi, [esi+SMEM.base]
  1453.            shr esi, 10
  1454.            lea edi, [page_tabs+eax]
  1455.            add esi, page_tabs
  1456.  
  1457.            mov edx, [access]
  1458.            or edx, [owner_access]
  1459.            shl edx, 1
  1460.            or edx, PG_USER+PG_SHARED
  1461. @@:
  1462.            lodsd
  1463.            and eax, 0xFFFFF000
  1464.            or eax, edx
  1465.            stosd
  1466.            loop @B
  1467.  
  1468.            xor edx, edx
  1469.  
  1470.            cmp [owner_access], 0
  1471.            jne .fail
  1472. .exit:
  1473.            mov edx, [size]
  1474. .fail:
  1475.            mov eax, [mapped]
  1476.  
  1477.            popfd
  1478.            pop edi
  1479.            pop esi
  1480.            pop ebx
  1481.            ret
  1482. .cleanup:
  1483.            mov [size], edx
  1484.            mov eax, esi
  1485.            call free
  1486.            jmp .exit
  1487.  
  1488. .cleanup2:
  1489.            mov [size], edx
  1490.            mov eax, edi
  1491.            call destroy_smap
  1492.            jmp .exit
  1493. endp
  1494.  
  1495. align 4
  1496. proc shmem_close stdcall, name:dword
  1497.  
  1498.            mov eax, [name]
  1499.            test eax, eax
  1500.            jz .fail
  1501.  
  1502.            push esi
  1503.            push edi
  1504.            pushfd
  1505.            cli
  1506.  
  1507.            mov esi, [current_slot]
  1508.            add esi, APP_OBJ_OFFSET
  1509. .next:
  1510.            mov eax, [esi+APPOBJ.fd]
  1511.            test eax, eax
  1512.            jz @F
  1513.  
  1514.            cmp eax, esi
  1515.            mov esi, eax
  1516.            je @F
  1517.  
  1518.            cmp [eax+SMAP.magic], 'SMAP'
  1519.            jne .next
  1520.  
  1521.            mov edi, [eax+SMAP.parent]
  1522.            test edi, edi
  1523.            jz .next
  1524.  
  1525.            lea edi, [edi+SMEM.name]
  1526.            stdcall strncmp, [name], edi, 32
  1527.            test eax, eax
  1528.            jne .next
  1529.  
  1530.            stdcall user_free, [esi+SMAP.base]
  1531.  
  1532.            mov eax,esi
  1533.            call [esi+APPOBJ.destroy]
  1534. @@:
  1535.            popfd
  1536.            pop edi
  1537.            pop esi
  1538. .fail:
  1539.            ret
  1540. endp
  1541.