home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c065 / 2.ddi / CLIB2.ZIP / NEARHEAP.ASM < prev    next >
Encoding:
Assembly Source File  |  1990-06-07  |  19.2 KB  |  600 lines

  1. ;[]-----------------------------------------------------------------[]
  2. ;|      NEARHEAP.ASM                                                 |
  3. ;|                                                                   |
  4. ;|      Turbo-C Run Time Library        Version 3.0                  |
  5. ;|                                                                   |
  6. ;|      Copyright (c) 1987,1988,1990 by Borland International Inc.   |
  7. ;|      All Rights Reserved.                                         |
  8. ;[]-----------------------------------------------------------------[]
  9.  
  10.     INCLUDE    RULES.ASI
  11.  
  12.     LOCALS
  13.     INCLUDE _HEAP.INC
  14.  
  15. IF LDATA EQ false
  16.  
  17. ;-----------------------------------------------------------------------
  18. ; Memory Block Header (near heap)
  19. ;-----------------------------------------------------------------------
  20. ; Each block in the heap, whether allocated or free, has a header.
  21. ; For an allocated block, only the first two fields of the header are
  22. ; used. For a free block all eight bytes are used, thus the smallest
  23. ; possible block is the size of a free header.
  24. ;
  25. ; Field       Description
  26. ; ---------   ----------------------------------------------------------
  27. ; size          total size, in bytes, of this block (+1 if the block is in use)
  28. ; prev_real   pointer to the physically previous block in the heap
  29. ; prev_free   pointer to the logically previous free block
  30. ; next_free   pointer to the logically next free block
  31. ;
  32. ; Note that the size field is also used to indicate whether the block
  33. ; is allocated or free.  A doubly-linked queue is maintained of the
  34. ; free blocks and it is important to know that ordering of the blocks
  35. ; in this queue is logical rather than physical.  If there is only one
  36. ; free block on the heap prev_free and next_free point to itself.
  37. ;-----------------------------------------------------------------------
  38. Header        STRUC
  39. bsize        dw    ?
  40. prev_real    dw    ?
  41. prev_free    dw    ?
  42. next_free    dw    ?
  43.         ENDS
  44.  
  45. ;-----------------------------------------------------------------------
  46. ; heapinfo structure (near heap)
  47. ;-----------------------------------------------------------------------
  48. ; Used by the heapwalk function.
  49. ; heapwalk accepts a pointer to a struct of this type.
  50. ; On entry, the pointer field contains the address of the previous
  51. ; memory block in the heap (NULL for the first call).  The next block
  52. ; in the heap is then found and its address is stored in the structure
  53. ; along with its size, in bytes, and a 'used' flag.
  54. ;-----------------------------------------------------------------------
  55. HeapInfo    STRUC
  56. hi_ptr        dw    ?
  57. hi_size     dw    ?
  58. hi_inuse    dw    ?
  59.         ENDS
  60.  
  61. UsedHeaderSize    EQU    4
  62. FreeHeaderSize    EQU    8
  63.  
  64. ;-----------------------------------------------------------------------
  65. ; Only three variables are needed to efficiently manage the heap.
  66. ;-----------------------------------------------------------------------
  67. _DATA        SEGMENT WORD PUBLIC 'DATA'
  68.                 PUBLIC  __first,__last,__rover
  69.         ALIGN    2
  70. __first         dw      0               ;pointer to the first block
  71. __last          dw      0               ;pointer to the last block
  72. __rover         dw      0               ;pointer to an arbitrary free block
  73. _DATA        ENDS
  74.  
  75. IF LPROG
  76.  EXTRADISP    equ    2         ; Allow for FAR returns when getting parms
  77. ELSE
  78.  EXTRADISP     equ    0
  79. ENDIF
  80.  
  81. DGROUP    GROUP    _DATA
  82.  
  83.         EXTRN    ___brk:NEAR, ___sbrk:NEAR
  84. _TEXT        SEGMENT PUBLIC 'CODE'
  85.         ASSUME CS:_TEXT,DS:DGROUP
  86.  
  87. ;-----------------------------------------------------------------------------
  88. ; C callable function to free a memory block
  89. ;-----------------------------------------------------------------------------
  90. ; Args:         Pointer to the block to free (stack)
  91. ; Returns:        void
  92. ;-----------------------------------------------------------------------------
  93.         PUBLIC    _free
  94. _free        PROC DIST
  95.         push    si
  96.         push    di
  97.         mov    si,sp
  98.         mov    bx,[si+(6+EXTRADISP)]    ;bx = first parameter passed
  99.         sub    bx,UsedHeaderSize    ;bx = the address of the block to free
  100.         jc    @@AllDone        ;skip if NULL
  101.                 cmp     bx,[__last]             ;is this the last block in the heap?
  102.                 je      @@lastBlock
  103. @@InnerBlock:
  104.         call    FreeInnerBlock        ;free the inner block
  105.         jmp    short @@AllDone
  106. @@LastBlock:
  107.         call    FreeLastBlock        ;free the last block
  108. @@AllDone:
  109.         pop    di            ;all done
  110.         pop    si
  111.         ret
  112. _free        ENDP
  113.  
  114. ;-----------------------------------------------------------------------------
  115. ; Frees the last block on the heap
  116. ; free helper function
  117. ;-----------------------------------------------------------------------------
  118. ; Args:         Pointer to the block (bx)
  119. ; Returns:        void
  120. ;-----------------------------------------------------------------------------
  121. FreeLastBlock    PROC NEAR
  122.                 cmp     [__first],bx            ;freeing the ONLY block?
  123.         je    @@KillHeap
  124.         mov    si,[bx.prev_real]    ;si = next-to-last block
  125.         test    BYTE PTR [si.bsize],01h
  126.         jz    @@PreviousBlockIsFree
  127. @@PreviousBlockIsUsed:
  128.                 mov     __last,si
  129.         jmp    short @@ResetBreak    ;done!
  130. @@PreviousBlockIsFree:
  131.                 cmp     si,[__first]            ;is the previous block the
  132.         je    @@ResetHeap        ;first block in the heap?
  133.  
  134.         mov    bx,si            ;remove the next-to-last block
  135.         call    PullFreeBlock        ;from the free-block queue
  136.         mov    ax,[bx.prev_real]
  137.                 mov     __last,ax
  138.         jmp    short @@ResetBreak    ;done!
  139. @@ResetHeap:
  140.         mov    bx,si
  141. ;we are freeing the only block so reset the break level and kill the heap
  142. @@KillHeap:
  143.         xor    ax,ax
  144.                 mov     __first,ax              ;clear variables
  145.                 mov     __last,ax
  146.                 mov     __rover,ax
  147. @@ResetBreak:
  148.         push    bx
  149.         call    ___brk            ;reset the break level
  150.         pop    bx            ;cleanup stack
  151.         ret
  152. FreeLastBlock    ENDP
  153.  
  154. ;-----------------------------------------------------------------------------
  155. ; Frees an interior block from within the heap
  156. ; free helper function
  157. ;-----------------------------------------------------------------------------
  158. ; Args:         Pointer to the block (bx)
  159. ; Returns:        void
  160. ;-----------------------------------------------------------------------------
  161. FreeInnerBlock    PROC NEAR
  162.         dec    WORD PTR [bx.bsize]    ;mark the block as free
  163.                 cmp     bx,[__first]            ;first block?
  164.         je    @@PreviousBlockIsUsed
  165.         mov    si,[bx.prev_real]    ;get the previous block (si)
  166.         mov    ax,[si.bsize]        ;is the previous block free?
  167.         test    al,01h
  168.         jnz    @@PreviousBlockIsUsed
  169. ; join this block to the previous block
  170. @@PreviousBlockIsFree:
  171.         add    ax,[bx.bsize]        ;add the size of this block to
  172.         mov    [si.bsize],ax        ;the size of the previous block
  173.         mov    di,[bx.bsize]        ;get the next block (di)
  174.         add    di,bx
  175.         mov    [di.prev_real],si    ;adjust the prev_real pointer
  176.         mov    bx,si            ;set up the current block
  177.         jmp    SHORT @@CheckNextBlock
  178. @@PreviousBlockIsUsed:
  179.         call    InsertFreeBlock     ;add it to the free queue
  180. @@CheckNextBlock:
  181.         mov    di,[bx.bsize]        ;get the next block (di)
  182.         add    di,bx
  183.         mov    ax,[di.bsize]        ;is the next block free?
  184.         test    al,01h
  185.         jz    JoinFreeBlocks        ;join this block to the next
  186. @@AllDone:
  187.         ret                ;all done
  188. FreeInnerBlock    ENDP
  189.  
  190. ;-----------------------------------------------------------------------------
  191. ; Joins two physically adjacent free blocks together
  192. ; free helper function
  193. ;-----------------------------------------------------------------------------
  194. ; Args:         Pointer to the lower block (bx)
  195. ;            Pointer to the upper block (di)
  196. ;            Size of the upper block, in bytes (ax)
  197. ; Returns:        void
  198. ; Registers destroyed:    ax si di
  199. ; This routine falls through to PullFreeBlock
  200. ;-----------------------------------------------------------------------------
  201. JoinFreeBlocks    PROC NEAR
  202.         add    [bx.bsize],ax        ;adjust the size of the lower block
  203.         mov    si,di            ;si = the next block after di
  204.         add    si,ax
  205.         mov    [si.prev_real],bx    ;adjust the link
  206.         mov    bx,di
  207. ;;;;        jmp    SHORT PullFreeBlock    ;eliminate the upper block
  208. JoinFreeBlocks    ENDP
  209.  
  210. ;-----------------------------------------------------------------------------
  211. ; Removes a block from the free block queue
  212. ; free helper function
  213. ; malloc helper function
  214. ;-----------------------------------------------------------------------------
  215. ; Args:         Pointer to the block (bx)
  216. ; Returns:        void
  217. ;-----------------------------------------------------------------------------
  218. PullFreeBlock    PROC NEAR
  219.         mov    di,[bx.next_free]    ;di = the next free block
  220.         cmp    bx,di            ;removing the last free block?
  221.         je    @@NoFreeBlocks
  222.                 mov     __rover,di
  223.         mov    si,[bx.prev_free]    ;si = previous free block
  224.         mov    [di.prev_free],si    ;adjust the links
  225.         mov    [si.next_free],di
  226.         ret                ;all done
  227. @@NoFreeBlocks:
  228.                 mov     __rover,0
  229.         ret                ;all done
  230. PullFreeBlock    ENDP
  231.  
  232. ;-----------------------------------------------------------------------------
  233. ; Inserts a block into the free block queue
  234. ; free helper function
  235. ;-----------------------------------------------------------------------------
  236. ; Args:         Pointer to the block (bx)
  237. ; Returns:        void
  238. ;-----------------------------------------------------------------------------
  239. InsertFreeBlock PROC NEAR
  240.                 mov     si,[__rover]            ;si = rover pointer
  241.         or    si,si            ;no free blocks?
  242.         jz    @@FirstFreeBlock
  243. @@AnotherFreeBlock:
  244.         mov    di,[si.next_free]    ;di = free block after rover
  245.         mov    [si.next_free],bx    ;adjust links
  246.         mov    [di.prev_free],bx
  247.         mov    [bx.next_free],di
  248.         mov    [bx.prev_free],si
  249.         ret
  250. @@FirstFreeBlock:
  251.                 mov     __rover,bx
  252.         mov    [bx.prev_free],bx
  253.         mov    [bx.next_free],bx
  254.         ret
  255. InsertFreeBlock ENDP
  256.  
  257.  
  258. ;-----------------------------------------------------------------------------
  259. ; C callable function to allocates a given number of bytes from the heap
  260. ;-----------------------------------------------------------------------------
  261. ; Args:         Number of bytes requested (stack)
  262. ; Returns:        Address of the first byte of user space available
  263. ;            from the heap if successful (ax)
  264. ;            NULL if failure (ax)
  265. ;-----------------------------------------------------------------------------
  266.         PUBLIC    _malloc
  267. _malloc     PROC DIST
  268.         push    si            ;should be on an odd address
  269.         push    di
  270.  
  271.         mov    si,sp
  272.         mov    ax,[si+(6+EXTRADISP)]    ;ax = number of bytes requested
  273.         or    ax,ax            ;does he want zero bytes?
  274.         jz    @@AllDone
  275.  
  276.         add    ax,UsedHeaderSize+1    ;add the header size
  277.         jc    @@NoCanDo        ;was size too great?
  278.         and    ax,0fffeh        ;force a word boundary
  279.         cmp    ax,FreeHeaderSize
  280.         jae    @@BigEnough
  281.         mov    ax,FreeHeaderSize
  282. @@BigEnough:
  283.                 cmp     [__first],0             ;do we have a heap yet?
  284.         jz    @@BuildHeap
  285.  
  286.                 mov     bx,[__rover]            ;bx = rover pointer
  287.         or    bx,bx            ;are there any free blocks at all?
  288.         jz    @@AddToHeap
  289.         mov    dx,bx            ;dx = rover pointer
  290. @@SearchHeap:
  291.         cmp    [bx.bsize],ax        ;big enough to use at all?
  292.         jae    @@AllocateBlock
  293. @@TooSmall:
  294.         mov    bx,[bx.next_free]    ;move to the next free block
  295.         cmp    bx,dx            ;at the end of the list?
  296.         jne    @@SearchHeap
  297. @@AddToHeap:
  298.         call    ExtendHeap
  299.         jmp    SHORT @@AllDone
  300. @@DivideFreeBlock:
  301.         call    AllocatePartialBlock
  302.         jmp    SHORT @@AllDone
  303. @@BuildHeap:
  304.         call    CreateHeap
  305.         jmp    SHORT @@AllDone
  306. @@NoCanDo:
  307.         xor    ax,ax
  308.         jmp    SHORT @@AllDone
  309. @@AllocateBlock:
  310.         mov    si,ax            ;si = smallest divisible block size
  311.         add    si,FreeHeaderSize
  312.         cmp    [bx.bsize],si        ;big enough to break up?
  313.         jae    @@DivideFreeBlock
  314.         call    PullFreeBlock        ;remove it from the free-block queue
  315.         inc    [bx.bsize]        ;mark it as allocated
  316.         mov    ax,bx
  317.         add    ax,UsedHeaderSize
  318. @@AllDone:
  319.         pop    di            ;all done
  320.         pop    si
  321.         ret
  322. _malloc     ENDP
  323.  
  324. ;-----------------------------------------------------------------------------
  325. ; Creates a heap from scratch
  326. ; malloc helper function
  327. ;-----------------------------------------------------------------------------
  328. ; Args:         Number of bytes for the first block requested (ax)
  329. ; Returns:        Address of the first byte of user space available
  330. ;            from the heap if successful (ax)
  331. ;            NULL if failure (ax)
  332. ;-----------------------------------------------------------------------------
  333. CreateHeap    PROC NEAR
  334.         push    ax            ;save the size
  335.  
  336.         xor    ax,ax            ;align the heap on word
  337.         push    ax
  338.         push    ax
  339.         call    ___sbrk         ;retrieve the break level
  340.         pop    bx            ;cleanup stack
  341.         pop    bx
  342.         and    ax,0001h
  343.         jz    @@Aligned
  344.         xor    dx,dx
  345.         push    dx
  346.         push    ax
  347.         call    ___sbrk         ;align the heap
  348.         pop    bx            ;cleanup stack
  349.         pop    bx
  350. @@Aligned:
  351.         pop    ax            ;retrieve and save the size
  352.         push    ax
  353.  
  354.         xor    bx,bx            ;convert size request from
  355.         push    bx            ;unsigned int to signed long
  356.         push    ax
  357.         call    ___sbrk         ;adjust the break level
  358.         pop    bx            ;cleanup stack
  359.         pop    bx
  360.         cmp    ax,-1            ;failure?
  361.         je    @@NoRoom
  362.         mov    bx,ax            ;bx = new block
  363.                 mov     __first,bx              ;save pointers
  364.                 mov     __last,bx
  365.         pop    ax            ;retrieve the size
  366.         inc    ax            ;mark it as allocated
  367.         mov    [bx.bsize],ax
  368.         add    bx,UsedHeaderSize
  369.         mov    ax,bx
  370.         ret
  371. @@NoRoom:
  372.         pop    bx            ;clear the size from the stack
  373.         xor    ax,ax
  374.         ret
  375. CreateHeap    ENDP
  376.  
  377. ;-----------------------------------------------------------------------------
  378. ; Attempts to extend the heap.
  379. ; malloc helper function
  380. ;-----------------------------------------------------------------------------
  381. ; Args:         Number of bytes for the block requested (ax)
  382. ; Returns:        Address of the first byte of user space available
  383. ;            from the heap if successful (ax)
  384. ;            NULL if failure (ax)
  385. ;-----------------------------------------------------------------------------
  386. ExtendHeap    PROC NEAR
  387.         push    ax            ;save the size
  388.         xor    bx,bx            ;convert size request from
  389.         push    bx            ;unsigned int to signed long
  390.         push    ax
  391.         call    ___sbrk         ;adjust the break level
  392.         pop    bx            ;cleanup stack
  393.         pop    bx
  394.         cmp    ax,-1            ;failure?
  395.         je    @@NoRoom
  396.         mov    bx,ax            ;bx = new block
  397.                 mov     ax,[__last]             ;ax = next-to-the-last block
  398.         mov    [bx.prev_real],ax
  399.                 mov     __last,bx               ;update last-block pointer
  400.         pop    ax            ;retrieve the size
  401.         inc    ax            ;mark it as allocated
  402.         mov    [bx.bsize],ax
  403.         add    bx,UsedHeaderSize
  404.         mov    ax,bx
  405.         ret
  406. @@NoRoom:    pop    ax            ;retrieve the size
  407.         xor    ax,ax
  408.         ret
  409. ExtendHeap    ENDP
  410.  
  411. ;-----------------------------------------------------------------------------
  412. ; Divides a free block into two pieces.
  413. ; malloc helper function
  414. ;-----------------------------------------------------------------------------
  415. ; Args:         Number of bytes for the block requested (ax)
  416. ;            Pointer of the block to divide (bx)
  417. ; Returns:        Address of the first byte of user space available
  418. ;            from the heap (ax)
  419. ;-----------------------------------------------------------------------------
  420. AllocatePartialBlock    PROC NEAR
  421.         sub    [bx.bsize],ax        ;make room!
  422.         mov    si,bx            ;si = new block address
  423.         add    si,[bx.bsize]
  424.         mov    di,si            ;di = the block after the new block
  425.         add    di,ax
  426.         inc    ax
  427.         mov    [si.bsize],ax
  428.         mov    [si.prev_real],bx
  429.         mov    [di.prev_real],si
  430.         add    si,UsedHeaderSize
  431.         mov    ax,si
  432.         ret
  433. AllocatePartialBlock    ENDP
  434.  
  435. ;-----------------------------------------------------------------------------
  436. ; Attempts to expand a block, relocating it if necessary
  437. ; realloc helper function
  438. ;-----------------------------------------------------------------------------
  439. ; Args:         Pointer to the old block (bx)
  440. ;            Size of the block (cx)
  441. ;            Number of bytes requested (ax)
  442. ; Returns:        Address of the first byte of user space available
  443. ;            from the heap if successful (bx)
  444. ;            NULL if failure (bx)
  445. ;-----------------------------------------------------------------------------
  446.  
  447. ExpandBlock    PROC NEAR
  448.         mov    bp,sp
  449.         push    bx            ;[bp-2] = old block
  450.         push    ax            ;[bp-4] = new size
  451.         push    cx            ;[bp-6] = old block size
  452.         push    ax
  453.         call    _malloc         ;ax = data area of new block
  454.         pop    bx            ;cleanup stack
  455.         or    ax,ax
  456.         jz    @@AllDone        ;malloc failed
  457. @@MallocOK:
  458.         push    ds            ;move the data to the new block
  459.         pop    es
  460.         cld
  461.         mov    di,ax            ;di = data area of new block
  462.         mov    si,[bp-2]        ;si = old block
  463.         mov    cx,[si.bsize]        ;cx = old block size
  464.         add    si,UsedHeaderSize    ;si = data area of old block
  465.         push    si            ;save for call to _free
  466.         sub    cx,UsedHeaderSize+1    ;cx = number of bytes in old data area
  467. @@MoveIt:
  468.         shr    cx,1            ;cx = number of words in data area
  469.         rep
  470.         movsw
  471.         mov    [bp-2],ax        ;save data area of new block in scratch area
  472.         call    _free
  473.         pop    bx            ;cleanup stack
  474.         mov    bx,[bp-2]
  475. @@AllDone:
  476.         add    sp,6
  477.         ret
  478. ExpandBlock    ENDP
  479.  
  480. ;-----------------------------------------------------------------------------
  481. ; Shrinks a block
  482. ; realloc helper function
  483. ;-----------------------------------------------------------------------------
  484. ; Args:         Pointer to the block (bx)
  485. ;            Size of the block (cx)
  486. ;            Normalized number of bytes requested (dx)
  487. ; Returns:        Address of the first byte of user space available
  488. ;            from the heap if successful (bx)
  489. ;-----------------------------------------------------------------------------
  490.  
  491. ShrinkBlock    PROC NEAR
  492.         mov    ax,dx            ;ax = requested block size
  493.         add    dx,FreeHeaderSize
  494.         cmp    dx,cx
  495.         ja    @@AllDone
  496.         mov    dx,cx            ;dx = old block size
  497. @@DivideTheBlock:
  498.                 cmp     bx,[__last]             ;last block in the heap?
  499.         jne    @@InnerBlock
  500. @@LastBlock:
  501.         mov    [bx.bsize],ax
  502.         inc    [bx.bsize]
  503.         add    ax,bx
  504.         push    bx            ;save the old block
  505.         push    ax
  506.         call    ___brk            ;reset the break level
  507.         pop    bx            ;cleanup stack
  508.         pop    bx            ;restore old block
  509.         jmp    SHORT @@AllDone
  510. @@InnerBlock:
  511.         mov    di,bx
  512.         add    di,ax            ;di = new (free) block
  513.         mov    [di.prev_real],bx
  514.         sub    dx,ax            ;dx = size of new (free) block
  515.         sub    [bx.bsize],dx
  516.         mov    si,di            ;si = next block after the new one
  517.         add    si,dx
  518.         mov    [si.prev_real],di    ;adjust the link
  519.         inc    dx            ;mark it as used
  520.         mov    [di.bsize],dx
  521.         mov    cx,bx            ;save the old block
  522.         mov    bx,di
  523.         call    FreeInnerBlock
  524.         mov    bx,cx            ;restore old block
  525. @@AllDone:
  526.         add    bx,UsedHeaderSize
  527.         ret
  528. ShrinkBlock    ENDP
  529.  
  530. ;-----------------------------------------------------------------------------
  531. ; Attempts to reallocate a block
  532. ;-----------------------------------------------------------------------------
  533. ; Args:         Pointer to the old block (stack)
  534. ;            Number of bytes requested (stack)
  535. ; Returns:        Address of the first byte of user space available
  536. ;            from the heap if successful (ax)
  537. ;            NULL if failure (ax)
  538. ;-----------------------------------------------------------------------------
  539.         PUBLIC    _realloc
  540. _realloc    PROC DIST
  541.         push    si
  542.         push    di
  543.         push    bp
  544.         mov    bp,sp
  545.  
  546.         mov    bx,[bp+(8+EXTRADISP)]    ;bx = pointer to the block to realloc
  547.         mov    ax,[bp+(10+EXTRADISP)]    ;ax = number of bytes requested
  548.  
  549.         or    ax,ax            ;does he really want 0 bytes???
  550.         jz    @@FreeIt        ;let's give him what he wants!
  551.  
  552.         or    bx,bx            ;did we get a NULL pointer?
  553.         jz    @@MallocIt        ;OK, try to malloc it
  554.  
  555.         sub    bx,UsedHeaderSize    ;make bx = start of block
  556.  
  557.         mov    cx,[bx.bsize]        ;cx = size of block
  558.         dec    cx
  559.         mov    dx,ax
  560.  
  561.         add    dx,UsedHeaderSize+1    ;add the header size and
  562.         and    dx,0fffeh        ;force a word boundary
  563.         cmp    dx,FreeHeaderSize
  564.         jae    @@BigEnough
  565.         mov    dx,FreeHeaderSize
  566. @@BigEnough:
  567.         cmp    cx,dx
  568.         jb    @@ExpandIt
  569.         ja    @@ShrinkIt
  570. @@NoChange:
  571.         add    bx,UsedHeaderSize
  572.         jmp    SHORT @@Resized
  573. @@ShrinkIt:
  574.         call    ShrinkBlock
  575.         jmp    SHORT @@Resized
  576. @@ExpandIt:
  577.         call    ExpandBlock
  578. @@Resized:
  579.         mov    ax,bx
  580.         jmp    SHORT @@AllDone
  581. @@MallocIt:
  582.         push    ax
  583.         call    _malloc
  584.         jmp    SHORT @@Cleanup
  585. @@FreeIt:
  586.         push    bx
  587.         call    _free
  588. @@Cleanup:
  589.         pop    bx            ;cleanup stack
  590. @@AllDone:
  591.         pop    bp            ;all done
  592.         pop    di
  593.         pop    si
  594.         ret
  595. _realloc    ENDP
  596.         ENDS
  597. ENDIF
  598.  
  599.         END
  600.