home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_144 / 2.ddi / CLIBSRC3.ZIP / NEARHEAP.ASM < prev    next >
Encoding:
Assembly Source File  |  1992-06-10  |  26.6 KB  |  604 lines

  1. ;[]-----------------------------------------------------------------[]
  2. ;|      NEARHEAP.ASM                                                 |
  3. ;[]-----------------------------------------------------------------[]
  4.  
  5. ;
  6. ;       C/C++ Run Time Library - Version 5.0
  7. ;       Copyright (c) 1987, 1992 by Borland International
  8. ;       All Rights Reserved.
  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.                 mov     bx,ax
  456.                 or      ax,ax
  457.                 jz      @@AllDone               ;malloc failed
  458. @@MallocOK:
  459.                 push    ds                      ;move the data to the new block
  460.                 pop     es
  461.                 cld
  462.                 mov     di,ax                   ;di = data area of new block
  463.                 mov     si,[bp-2]               ;si = old block
  464.                 mov     cx,[si.bsize]           ;cx = old block size
  465.                 add     si,UsedHeaderSize       ;si = data area of old block
  466.                 push    si                      ;save for call to _free
  467.                 sub     cx,UsedHeaderSize+1     ;cx = number of bytes in old data area
  468. @@MoveIt:
  469.                 shr     cx,1                    ;cx = number of words in data area
  470.                 rep
  471.                 movsw
  472.                 mov     [bp-2],ax               ;save data area of new block in scratch area
  473.                 call    _free
  474.                 pop     bx                      ;cleanup stack
  475.                 mov     bx,[bp-2]
  476. @@AllDone:
  477.                 add     sp,6
  478.                 ret
  479. ExpandBlock     ENDP
  480.  
  481. ;-----------------------------------------------------------------------------
  482. ; Shrinks a block
  483. ; realloc helper function
  484. ;-----------------------------------------------------------------------------
  485. ; Args:                 Pointer to the block (bx)
  486. ;                       Size of the block (cx)
  487. ;                       Normalized number of bytes requested (dx)
  488. ; Returns:              Address of the first byte of user space available
  489. ;                       from the heap if successful (bx)
  490. ;-----------------------------------------------------------------------------
  491.  
  492. ShrinkBlock     PROC NEAR
  493.                 mov     ax,dx                   ;ax = requested block size
  494.                 add     dx,FreeHeaderSize
  495.                 cmp     dx,cx
  496.                 ja      @@AllDone
  497.                 mov     dx,cx                   ;dx = old block size
  498. @@DivideTheBlock:
  499.                 cmp     bx,[__last]             ;last block in the heap?
  500.                 jne     @@InnerBlock
  501. @@LastBlock:
  502.                 mov     [bx.bsize],ax
  503.                 inc     [bx.bsize]
  504.                 add     ax,bx
  505.                 push    bx                      ;save the old block
  506.                 push    ax
  507.                 call    ___brk                  ;reset the break level
  508.                 pop     bx                      ;cleanup stack
  509.                 pop     bx                      ;restore old block
  510.                 jmp     SHORT @@AllDone
  511. @@InnerBlock:
  512.                 mov     di,bx
  513.                 add     di,ax                   ;di = new (free) block
  514.                 mov     [di.prev_real],bx
  515.                 sub     dx,ax                   ;dx = size of new (free) block
  516.                 sub     [bx.bsize],dx
  517.                 mov     si,di                   ;si = next block after the new one
  518.                 add     si,dx
  519.                 mov     [si.prev_real],di       ;adjust the link
  520.                 inc     dx                      ;mark it as used
  521.                 mov     [di.bsize],dx
  522.                 mov     cx,bx                   ;save the old block
  523.                 mov     bx,di
  524.                 call    FreeInnerBlock
  525.                 mov     bx,cx                   ;restore old block
  526. @@AllDone:
  527.                 add     bx,UsedHeaderSize
  528.                 ret
  529. ShrinkBlock     ENDP
  530.  
  531. ;-----------------------------------------------------------------------------
  532. ; Attempts to reallocate a block
  533. ;-----------------------------------------------------------------------------
  534. ; Args:                 Pointer to the old block (stack)
  535. ;                       Number of bytes requested (stack)
  536. ; Returns:              Address of the first byte of user space available
  537. ;                       from the heap if successful (ax)
  538. ;                       NULL if failure (ax)
  539. ;-----------------------------------------------------------------------------
  540.                 PUBLIC  _realloc
  541. _realloc        PROC DIST
  542.                 push    si
  543.                 push    di
  544.                 push    bp
  545.                 mov     bp,sp
  546.  
  547.                 mov     bx,[bp+(8+EXTRADISP)]   ;bx = pointer to the block to realloc
  548.                 mov     ax,[bp+(10+EXTRADISP)]  ;ax = number of bytes requested
  549.  
  550.                 or      ax,ax                   ;does he really want 0 bytes???
  551.                 jz      @@FreeIt                ;let's give him what he wants!
  552.  
  553.                 or      bx,bx                   ;did we get a NULL pointer?
  554.                 jz      @@MallocIt              ;OK, try to malloc it
  555.  
  556.                 sub     bx,UsedHeaderSize       ;make bx = start of block
  557.  
  558.                 mov     cx,[bx.bsize]           ;cx = size of block
  559.                 dec     cx
  560.                 mov     dx,ax
  561.  
  562.                 add     dx,UsedHeaderSize+1     ;add the header size and
  563.                 and     dx,0fffeh               ;force a word boundary
  564.                 cmp     dx,FreeHeaderSize
  565.                 jae     @@BigEnough
  566.                 mov     dx,FreeHeaderSize
  567. @@BigEnough:
  568.                 cmp     cx,dx
  569.                 jb      @@ExpandIt
  570.                 ja      @@ShrinkIt
  571. @@NoChange:
  572.                 add     bx,UsedHeaderSize
  573.                 jmp     SHORT @@Resized
  574. @@ShrinkIt:
  575.                 call    ShrinkBlock
  576.                 jmp     SHORT @@Resized
  577. @@ExpandIt:
  578.                 call    ExpandBlock
  579. @@Resized:
  580.                 mov     ax,bx
  581.                 jmp     SHORT @@AllDone
  582. @@MallocIt:
  583.                 push    ax
  584.                 call    _malloc
  585.                 jmp     SHORT @@Cleanup
  586. @@FreeIt:
  587.                 push    bx
  588.                 call    _free
  589.                 xor     ax, ax
  590. @@Cleanup:
  591.                 pop     bx                      ;cleanup stack
  592. @@AllDone:
  593.                 pop     bp                      ;all done
  594.                 pop     di
  595.                 pop     si
  596.                 ret
  597. _realloc        ENDP
  598.                 ENDS
  599. ENDIF
  600.  
  601.                 END
  602.