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

  1. ;[]-----------------------------------------------------------------[]
  2. ;|      FARHEAP.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. ;-----------------------------------------------------------------------
  16. ; Memory Block Header (far heap)
  17. ;-----------------------------------------------------------------------
  18. ; Each block in the heap, whether allocated or free, has a header.
  19. ; For an allocated block, only the first two fields of the header are
  20. ; used. For a free block all ten bytes are used.  Blocks are aligned on
  21. ; paragraph boundaries, thus the smallest possible block sixteen bytes.
  22. ;
  23. ; Field       Description
  24. ; ---------   ----------------------------------------------------------
  25. ; size        total size, in paragraphs, of this block
  26. ; prev_real   segment of the physically previous block in the heap
  27. ;          prev_real is 0 this block is free, get the prev_real from prev_real2
  28. ; prev_free   segment of the logically previous free block
  29. ; next_free   segment of the logically next free block
  30. ; prev_real2  segment of the physically previous block in the heap
  31. ; free_space  first byte of free space available
  32. ;
  33. ; A doubly-linked queue is maintained of the free blocks and it is important 
  34. ; to know that ordering of the blocks in this queue is logical rather than 
  35. ; physical.  If there is only one free block on the heap prev_free and 
  36. ; next_free point to itself.
  37. ;-----------------------------------------------------------------------
  38. bsize        EQU    0
  39. prev_real    EQU    2
  40. prev_free    EQU    4
  41. next_free    EQU    6
  42. prev_real2    EQU    8
  43. free_space    EQU    10
  44.  
  45. ;-----------------------------------------------------------------------
  46. ; heapinfo structure (far 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        dd    ?
  57. hi_size        dd    ?
  58. hi_inuse    dw    ?
  59.         ENDS
  60.  
  61. UsedHeaderSize    EQU    4
  62. FreeHeaderSize    EQU    10
  63.  
  64.         EXTRN    __brk:NEAR, __sbrk:NEAR
  65. _TEXT           SEGMENT PUBLIC 'CODE'
  66.         ASSUME CS:_TEXT        
  67.  
  68. ;-----------------------------------------------------------------------
  69. ; Only three variables are needed to efficiently manage the heap.
  70. ; These reside in our own code segment for speed.
  71. ; We also set aside some scratch save areas.
  72. ;-----------------------------------------------------------------------
  73.                 PUBLIC  ___first,___last,___rover
  74.         ALIGN    2
  75. ___first        dw      0               ;segment of the first block
  76. ___last         dw      0               ;segment of the last block
  77. ___rover        dw      0               ;segment of an arbitrary free block
  78. data_seg    dw    ?        ;old ds save area
  79. save_hi        dw    ?        ;for realloc
  80. save_lo        dw    ?
  81.  
  82. ;-----------------------------------------------------------------------------
  83. ; Frees the last block on the heap
  84. ; free helper function
  85. ;-----------------------------------------------------------------------------
  86. ; Args:                 Pointer to the block (dx)
  87. ; Returns:              void
  88. ;-----------------------------------------------------------------------------
  89. FreeLastBlock    PROC    NEAR
  90.                 cmp     dx,cs:[___first]           ;are we freeing the ONLY block?
  91.         je    @@KillHeap
  92.         mov    ds,dx
  93.         mov    ds,ds:[prev_real]    ;ds = next-to-last block
  94.         cmp    WORD PTR ds:[prev_real],0    ;is the previous block used?
  95.         je    @@PreviousBlockIsFree
  96. @@PreviousBlockIsUsed:
  97.                 mov     cs:___last,ds
  98.                 jmp     short @@Cleanup1
  99.  
  100. @@PreviousBlockIsFree:
  101.         mov    ax,ds
  102.                 cmp     ax,cs:[___first]        ;is the previous block the
  103.         je    @@ResetHeap        ;first block in the heap?
  104.         mov    ax,ds:[prev_real2]
  105.                 mov     cs:___last,ax
  106.         push    ds            ;save for call to __brk
  107.         xor    ax,ax
  108.         push    ax
  109.         call    PullFreeBlock
  110.         mov    ds,cs:[data_seg]
  111.                 jmp     short @@Cleanup2
  112. @@ResetHeap:
  113.                 mov     dx,cs:[___first]
  114. @@KillHeap:
  115.                 mov     cs:___first,0
  116.                 mov     cs:___last,0
  117.                 mov     cs:___rover,0
  118. @@Cleanup1:
  119.         mov    ds,cs:[data_seg]
  120.         push    dx
  121.         xor    ax,ax
  122.         push    ax
  123. @@Cleanup2:
  124.         call    __brk            ;reset the break level
  125.                 pop     ax                      ;cleanup stack
  126.                 pop     ax
  127.         ret
  128.         ENDP
  129.  
  130. ;-----------------------------------------------------------------------------
  131. ; Frees an interior block from within the heap
  132. ; free helper function
  133. ;-----------------------------------------------------------------------------
  134. ; Args:                 Pointer to the block (dx)
  135. ; Returns:              void
  136. ;-----------------------------------------------------------------------------
  137. FreeInnerBlock    PROC    NEAR
  138.         mov    ds,dx            ;ds = block to free
  139.         push    ds            ;save block address
  140.         mov    es,ds:[prev_real]     ;es = previous block
  141.         mov    WORD PTR ds:[prev_real],0    ;mark the block as free
  142.         mov    ds:[prev_real2],es      
  143.                 cmp     dx,cs:[___first]           ;freeing first block?
  144.         je    @@PreviousBlockIsUsed
  145.         cmp    WORD PTR es:[prev_real],0    ;is the previous block free?
  146.         jne    @@PreviousBlockIsUsed
  147. @@PreviousBlockIsFree:
  148.         mov    ax,ds:[bsize]        ;ax = size of this block
  149.         pop    bx
  150.         push    es
  151.         add    es:[bsize],ax        ;add it to the previous block
  152.         mov    cx,es            ;cx = previous block
  153.         add    dx,ax            ;dx = next block
  154.         mov    es,dx            ;es = next block
  155.         cmp    WORD PTR es:[prev_real],0
  156.         jne    @@NextBlockIsUsed
  157. @@NextBlockIsFree:
  158.         mov    es:[prev_real2],cx
  159.         jmp    SHORT @@CheckNextBlock
  160. @@NextBlockIsUsed:
  161.         mov    es:[prev_real],cx
  162.         jmp    SHORT @@CheckNextBlock
  163.  
  164. @@PreviousBlockIsUsed:
  165.         call    InsertFreeBlock
  166.  
  167. @@CheckNextBlock:
  168.         pop    es            ;es = retrieve block
  169.         mov    ax,es            ;ax = block
  170.         add    ax,es:[bsize]        ;ax = next block
  171.         mov    ds,ax            ;ds = next block
  172.         cmp    WORD PTR ds:[prev_real],0    ;is next block free?
  173.         je    JoinFreeBlocks
  174. @@AllDone:
  175.         ret
  176.         ENDP
  177.  
  178. ;-----------------------------------------------------------------------------
  179. ; Joins two physically adjacent free blocks together
  180. ; free helper function
  181. ;-----------------------------------------------------------------------------
  182. ; Args:                 Pointer to the lower block (es)
  183. ;                       Pointer to the upper block (ds)
  184. ; Returns:              void
  185. ; This routine falls through to PullFreeBlock
  186. ;-----------------------------------------------------------------------------
  187. JoinFreeBlocks    PROC    NEAR
  188.         mov    ax,ds:[bsize]        ;ax = size of upper block
  189.         add    es:[bsize],ax        ;add it to lower block size
  190.         mov    ax,es            ;ax = lower block
  191.         mov    bx,ds            ;bx = upper block
  192.         add    bx,ds:[bsize]        ;bx = next block
  193.         mov    es,bx            ;es = next block
  194.         mov    es:[prev_real],ax    ;fixup link
  195. ;;;;        jmp    SHORT PullFreeBlock
  196.         ENDP
  197.  
  198. ;-----------------------------------------------------------------------------
  199. ; Removes a block from the free block queue
  200. ; free helper function
  201. ; malloc helper function
  202. ;-----------------------------------------------------------------------------
  203. ; Args:                 Pointer to the block (ds)
  204. ; Returns:              void
  205. ;-----------------------------------------------------------------------------
  206. PullFreeBlock    PROC    NEAR
  207.         mov    bx,ds            ;bx = this block
  208.         cmp    bx,ds:[next_free]    ;only ONE free block?
  209.         je    @@NoFreeBlocks
  210.         mov    es,ds:[next_free]    ;es = next free block
  211.         mov    ds,ds:[prev_free]    ;ds = previous free block
  212.         mov    ds:[next_free],es
  213.         mov    es:[prev_free],ds
  214.                 mov     cs:___rover,ds
  215.         mov    ds,bx
  216.         ret
  217. @@NoFreeBlocks:
  218.                 mov     cs:___rover,0
  219.         ret
  220.         ENDP
  221.  
  222. ;-----------------------------------------------------------------------------
  223. ; Inserts a block into the free block queue
  224. ; free helper function
  225. ;-----------------------------------------------------------------------------
  226. ; Args:                 Pointer to the block (ds)
  227. ; Returns:              void
  228. ;-----------------------------------------------------------------------------
  229. InsertFreeBlock    PROC    NEAR
  230.                 mov     ax,cs:[___rover]        ;ax = rover pointer
  231.         or    ax,ax            ;no free blocks?
  232.                 jz      @@firstFreeBlock
  233.         mov    bx,ss            ;save ss
  234.                 cli                             ;XXXXXXXXXXXXXXXXXXXXX
  235.         mov    ss,ax            ;ss = rover pointer
  236.         mov    es,ss:[next_free]    ;es = next free block
  237.         mov    ss:next_free,ds        ;fixup links
  238.         mov    ds:prev_free,ss
  239.         mov    ss,bx            ;restore ss
  240.                 sti                             ;XXXXXXXXXXXXXXXXXXXXX
  241.         mov    es:prev_free,ds
  242.         mov    ds:next_free,es
  243.         ret
  244.  
  245. @@FirstFreeBlock:
  246.                 mov     cs:___rover,ds
  247.         mov    ds:[prev_free],ds
  248.         mov    ds:[next_free],ds
  249.         ret
  250.         ENDP
  251.  
  252.  
  253. ;-----------------------------------------------------------------------------
  254. ; C callable function to free a memory block
  255. ;-----------------------------------------------------------------------------
  256. ; Args:                 Pointer to the block to free (stack)
  257. ; Returns:              void
  258. ;-----------------------------------------------------------------------------
  259. IF LDATA
  260.         PUBLIC    _free
  261. _free        LABEL    DIST
  262. ENDIF
  263.         PUBLIC    _farfree
  264. _farfree    PROC DIST
  265.                 ARG     O:word, S:word
  266.  
  267.                 push    bp
  268.                 mov     bp,sp
  269.                 push    si
  270.                 push    di
  271.  
  272.         mov    cs:data_seg,ds
  273.         mov    dx,[S]          ;dx = segment to free
  274.                 or      dx,dx                   ;is it NULL
  275.         jz    @@AllDone               ;   yes, skip it
  276.                 cmp     dx,cs:[___last]         ;last block in the heap?
  277.         jne    @@InnerBlock
  278. @@LastBlock:
  279.         call    FreeLastBlock
  280.         jmp    SHORT @@AllDone
  281. @@InnerBlock:
  282.         call    FreeInnerBlock
  283. @@AllDone:
  284.         mov    ds,cs:[data_seg]
  285.         pop    di
  286.         pop    si
  287.         pop    bp
  288.         ret
  289.         ENDP
  290.  
  291. ;-----------------------------------------------------------------------------
  292. ; Creates a heap from scratch
  293. ; malloc helper function
  294. ;-----------------------------------------------------------------------------
  295. ; Args:                 Number of paragraphs for the first block requested (ax)
  296. ; Returns:              Address of the first byte of user space available
  297. ;            from the heap if successful (dx:ax)
  298. ;            NULL if failure (dx:ax)        
  299. ;-----------------------------------------------------------------------------
  300. CreateHeap    PROC    NEAR
  301.         push    ax            ;save the size
  302.  
  303.         mov    ds,cs:[data_seg]
  304.         xor    ax,ax            ;align the heap on paragraph
  305.         push    ax
  306.         push    ax
  307.         call    __sbrk             ;retrieve the break level
  308.                 pop     bx                      ;cleanup stack
  309.                 pop     bx
  310.         and    ax,000fh
  311.         jz    @@Aligned
  312.         mov    dx,16d
  313.         sub    dx,ax
  314.         xor    ax,ax
  315.         mov    ds,cs:[data_seg]
  316.         push    ax
  317.         push    dx
  318.         call    __sbrk             ;align the heap
  319.                 pop     bx                      ;cleanup stack
  320.                 pop     bx
  321. @@Aligned:
  322.         pop    ax            ;retrieve and save the size
  323.         push    ax
  324.  
  325.         xor    bx,bx            ;convert size to long in bx:ax
  326.         mov    bl,ah
  327.                 mov     cl,4
  328.         shr    bx,cl
  329.         shl    ax,cl
  330.  
  331.         mov    ds,cs:[data_seg]
  332.         push    bx
  333.         push    ax
  334.         call    __sbrk             ;adjust the break level
  335.         pop    bx            ;cleanup stack
  336.         pop    bx
  337.  
  338.         pop    bx            ;retrieve the size
  339.  
  340.         cmp    ax,-1            ;failure?
  341.         je    @@NoRoom
  342.  
  343.                 mov     cs:___first,dx          ;update heap pointers
  344.                 mov     cs:___last,dx
  345.         mov    ds,dx
  346.         mov    WORD PTR ds:[bsize],bx
  347.         mov    WORD PTR ds:[prev_real],dx   ;just so we know it is used
  348.         mov    ax,UsedHeaderSize
  349.         ret
  350. @@NoRoom:
  351.         xor    ax,ax
  352.                 cwd
  353.         ret
  354.         ENDP
  355.  
  356. ;-----------------------------------------------------------------------------
  357. ; Attempts to extend the heap.
  358. ; malloc helper function
  359. ;-----------------------------------------------------------------------------
  360. ; Args:                 Number of paragraphs for the block requested (ax)
  361. ; Returns:              Address of the first byte of user space available
  362. ;            from the heap if successful (dx:ax)
  363. ;            NULL if failure (dx:ax)        
  364. ;-----------------------------------------------------------------------------
  365. ExtendHeap    PROC    NEAR
  366.         push    ax            ;save the size
  367.  
  368.         xor    bx,bx            ;convert size to long in bx:ax
  369.         mov    bl,ah
  370.                 mov     cl,4
  371.         shr    bx,cl
  372.         shl    ax,cl
  373.  
  374.         mov    ds,cs:[data_seg]
  375.         push    bx
  376.         push    ax
  377.         call    __sbrk             ;adjust the break level
  378.         pop    bx            ;cleanup stack
  379.         pop    bx
  380.  
  381.         pop    bx            ;retrieve the size
  382.  
  383.         cmp    ax,-1            ;failure?
  384.         je    @@NoRoom
  385.  
  386.                 mov     cx,cs:[___last]         ;cx = old last-block pointer
  387.                 mov     cs:___last,dx           ;update last-block pointer
  388.         mov    ds,dx
  389.         mov    WORD PTR ds:[bsize],bx
  390.         mov    WORD PTR ds:[prev_real],cx
  391.         mov    ax,UsedHeaderSize
  392.         ret
  393. @@NoRoom:
  394.         xor    ax,ax
  395.                 cwd
  396.         ret
  397.         ENDP
  398.  
  399. ;-----------------------------------------------------------------------------
  400. ; Divides a free block into two pieces.
  401. ; malloc helper function
  402. ;-----------------------------------------------------------------------------
  403. ; Args:                 Number of paragraphs for the block requested (ax)
  404. ;            Pointer of the block to divide (ds & dx)
  405. ; Returns:              Address of the first byte of user space available
  406. ;            from the heap (dx:ax)
  407. ;-----------------------------------------------------------------------------
  408. AllocatePartialBlock    PROC    NEAR
  409.         mov    bx,dx            ;save block
  410.         sub    ds:[bsize],ax        ;make room for new block
  411.         add    dx,ds:[bsize]
  412.         mov    ds,dx            ;ds = new block
  413.         mov    ds:[bsize],ax
  414.         mov    ds:[prev_real],bx
  415.         mov    bx,dx            ;save block
  416.         add    bx,ds:[bsize]
  417.         mov    ds,bx            ;ds = next block
  418.         mov    ds:[prev_real],dx
  419.         mov    ax,UsedHeaderSize
  420.         ret
  421.         ENDP
  422.  
  423. ;-----------------------------------------------------------------------------
  424. ; C callable function to allocates a given number of bytes from the far heap
  425. ;-----------------------------------------------------------------------------
  426. ; Args:                 Number of bytes requested (long, stack)
  427. ; Returns:              Address of the first byte of user space available
  428. ;            from the heap if successful (dx:ax)
  429. ;            NULL if failure (ds:ax)        
  430. ;-----------------------------------------------------------------------------
  431.         PROC    GenericMalloc DIST
  432. IF LDATA
  433.         PUBLIC    _malloc
  434. _malloc        LABEL    DIST
  435.                 ARG     R2:word
  436.  
  437.                 push    bp
  438.                 mov     bp,sp
  439.         xor    dx,dx
  440.         mov    ax,[R2]          ;dx:ax = size requested (long)
  441.         jmp    SHORT @@GotTheSize
  442. ENDIF
  443.         PUBLIC    _farmalloc
  444. _farmalloc    LABEL    DIST
  445.                 ARG     R2:word, R1:word
  446.  
  447.                 push    bp
  448.                 mov     bp,sp
  449.         mov    dx,[R1]
  450.         mov    ax,[R2]         ;dx:ax = size requested (long)
  451. @@GotTheSize:
  452.                 push    si
  453.                 push    di
  454.         mov    cs:data_seg,ds
  455.         mov    cx,ax
  456.         or    cx,dx            ;does he want 0 bytes?
  457.         jz    @@AllDone
  458.  
  459.         add    ax,UsedHeaderSize+15    ;add the header size and
  460.         adc    dx,0            ;force paragraph boundary
  461.         jc    @@NoCanDo        ;size too big?
  462.         test    dx,0fff0h
  463.         jnz    @@NoCanDo        ;size too big?
  464.                 mov     cl,4
  465.         shr    ax,cl
  466.         shl    dx,cl
  467.         or    ah,dl            ;ax = number of paragraphs
  468.  
  469.                 mov     dx,cs:[___first]        ;dx = first block in the heap
  470.         or    dx,dx               ;is there any heap at all?
  471.         jz    @@BuildHeap
  472.  
  473.                 mov     dx,cs:[___rover]        ;dx = rover pointer
  474.         or    dx,dx
  475.         jz    @@AddToHeap
  476.  
  477.         mov    bx,dx            ;bx = rover pointer
  478. @@SearchHeap:
  479.         mov    ds,dx            ;ds = free block
  480.         cmp    ds:[bsize],ax        ;is it big enough?
  481.         jae    @@AllocateBlock
  482. @@TooSmall:
  483.         mov    dx,ds:[next_free]    ;dx = next free block
  484.         cmp    dx,bx            ;are we done?
  485.         jne    @@SearchHeap
  486. @@AddToHeap:
  487.         call    ExtendHeap
  488.         jmp    SHORT @@AllDone
  489. @@BuildHeap:
  490.         call    CreateHeap
  491.         jmp    SHORT @@AllDone
  492. @@DivideFreeBlock:
  493.         call    AllocatePartialBlock
  494.         jmp    SHORT @@AllDone
  495. @@NoCanDo:
  496.         xor    ax,ax
  497.                 cwd
  498.         jmp    SHORT @@AllDone
  499. @@AllocateBlock:
  500.         ja    @@DivideFreeBlock
  501.         call    PullFreeBlock        ;remove it from the free-block queue
  502.         mov    bx,ds:[prev_real2]    ;mark it as allocated
  503.         mov    ds:[prev_real],bx
  504.         mov    ax,UsedHeaderSize
  505. @@AllDone:
  506.         mov    ds,cs:[data_seg]
  507.                 pop     di
  508.                 pop     si
  509.                 pop     bp
  510.         ret
  511.         ENDP
  512.  
  513. ;-----------------------------------------------------------------------------
  514. ; Attempts to expand a block, relocating it if necessary
  515. ; realloc helper function
  516. ;-----------------------------------------------------------------------------
  517. ; Args:                 Pointer to the old block (bx)
  518. ;            Number of paragraphs requested (ax)
  519. ; Returns:              Address of the first byte of user space available
  520. ;            from the heap if successful (dx:ax)
  521. ;            NULL if failure (dx:ax)        
  522. ;-----------------------------------------------------------------------------
  523.  
  524. ExpandBlock    PROC    NEAR
  525.         push    bx            ;save the old block
  526.         mov    si,cs:[save_hi]        ;get size parms from _farrealloc
  527.         push    si              ;setup for _farmalloc
  528.         mov    si,cs:[save_lo]        ;get size parms from _farrealloc
  529.         push    si            ;setup for _farmalloc
  530.         call    _farmalloc
  531.                 pop     bx                      ;cleanup stack
  532.                 pop     bx
  533.         or    dx,dx
  534.         jnz    @@MallocOK
  535. @@MallocFailed:
  536.                 pop     bx                      ;cleanup stack
  537.         ret
  538. @@MallocOK:
  539.         pop    ds            ;ds = old block
  540.         mov    es,dx            ;es = new block
  541.         push    es              ;save new block
  542.         push    ds            ;save old block for _farfree
  543.                 push    bx
  544.  
  545.         mov    dx,ds:[bsize]        ;dx = old block size
  546. @@MoveFirstBlock:
  547.         cld
  548.         dec    dx            ;subtract one paragraph
  549.         mov    di,UsedHeaderSize
  550.         mov    si,di
  551.         mov    cx,(16d-UsedHeaderSize)/2
  552.         rep    
  553.         movsw
  554.         or    dx,dx
  555.         jz    @@FreeOldBlock
  556.         mov    ax,es            ;increment segments
  557.         inc    ax
  558.         mov    es,ax
  559.         mov    ax,ds
  560.         inc    ax
  561.         mov    ds,ax
  562. @@MoveLoop:
  563.         xor    di,di
  564.         mov    si,di
  565.         mov    cx,dx            ;cx = paragraphs remaining
  566.         cmp    cx,1000h
  567.         jbe    @@MoveIt
  568.         mov    cx,1000h
  569. @@MoveIt:    shl    cx,1            ;cx = number of words
  570.         shl    cx,1
  571.         shl    cx,1
  572.         rep
  573.         movsw
  574.         sub    dx,1000h
  575.         jbe    @@FreeOldBlock
  576.         mov    ax,es            ;increment segments
  577.         add    ax,1000h        ;add 64k
  578.         mov    es,ax
  579.         mov    ax,ds
  580.         add    ax,1000h        ;add 64k
  581.         mov    ds,ax
  582.         jmp    SHORT @@MoveLoop
  583. @@FreeOldBlock:
  584.         mov    ds,cs:[data_seg]
  585.         call    _farfree        ;free the old block
  586.         pop    dx                      ;cleanup stack
  587.         pop    dx
  588.  
  589.         pop    dx
  590.         mov    ax,UsedHeaderSize
  591. @@AllDone:
  592.         ret
  593.         ENDP
  594.  
  595. ;-----------------------------------------------------------------------------
  596. ; Shrinks a block
  597. ; realloc helper function
  598. ;-----------------------------------------------------------------------------
  599. ; Args:                 Pointer to the block (bx)
  600. ;            Size of the block (cx)
  601. ;            Normalized number of paragraphs requested (ax)
  602. ; Returns:              Address of the first byte of user space available
  603. ;            from the heap if successful (dx:ax)
  604. ;-----------------------------------------------------------------------------
  605.  
  606. ShrinkBlock    PROC    NEAR
  607.                 cmp     bx,cs:[___last]         ;last block in the heap?
  608.         je    @@LastBlock
  609. @@InnerBlock:
  610.         mov    di,bx            ;di = old block
  611.         add    di,ax            ;di = new block
  612.         mov    es,di            ;es = new block
  613.         mov    si,cx            ;si = old block size
  614.         sub    si,ax            ;si -= new block size
  615.         mov    es:[bsize],si         ;setup new block    
  616.         mov    es:[prev_real],bx
  617.         push    es            ;save for _farfree
  618.  
  619.         push    ax
  620.  
  621.         mov    es,bx            ;es = original block
  622.         mov    es:[bsize],ax
  623.         mov    dx,bx            ;dx = old block
  624.         add    dx,cx            ;dx = block after new
  625.         mov    es,dx            ;es = block after new
  626.         cmp    WORD PTR es:[prev_real],0    ;is it used?
  627.         je    @@NextIsFree
  628. @@NextIsUsed:
  629.         mov    es:[prev_real],di
  630.         jmp    SHORT @@UnlinkIt
  631. @@NextIsFree:
  632.         mov    es:[prev_real2],di
  633. @@UnlinkIt:
  634.         mov    si,bx            ;si = old block
  635.         call    _farfree
  636.                 pop     dx                      ;cleanup stack
  637.                 pop     dx
  638.         mov    dx,si
  639.         mov    ax,UsedHeaderSize
  640.         ret
  641. @@LastBlock:
  642.         push    bx            ;save block
  643.         mov    es,bx
  644.         mov    es:[bsize],ax
  645.         add    bx,ax
  646.         push    bx
  647.         xor    ax,ax
  648.         push    ax
  649.         call    __brk            ;reset the break level
  650.                 pop     dx                      ;cleanup stack
  651.                 pop     dx
  652.  
  653.         pop    dx            ;restore block
  654.         mov    ax,UsedHeaderSize
  655.         ret
  656.         ENDP
  657.  
  658. ;-----------------------------------------------------------------------------
  659. ; Attempts to reallocate a block
  660. ;-----------------------------------------------------------------------------
  661. ; Args:                 Pointer to the old block (stack)
  662. ;            Number of bytes requested (stack)
  663. ; Returns:              Address of the first byte of user space available
  664. ;            from the heap if successful (dx:ax)
  665. ;            NULL if failure (dx:ax)        
  666. ;-----------------------------------------------------------------------------
  667.         PROC    GenericRealloc DIST
  668. IF LDATA
  669.         PUBLIC    _realloc
  670. _realloc    LABEL    DIST
  671.                 ARG     O:word, S:word, LO:word
  672.         push    bp
  673.         mov    bp,sp
  674.         xor    dx,dx
  675.         jmp    SHORT @@GetTheSize
  676. ENDIF
  677.         PUBLIC    _farrealloc
  678. _farrealloc    LABEL    DIST
  679.                 ARG     O:word, S:word, LO:word, HI:word
  680.         push    bp
  681.         mov    bp,sp
  682.         mov    dx,[HI]
  683. @@GetTheSize:
  684.         mov    ax,[LO]            ;dx:ax = size requested (long)
  685.         mov    bx,[S]            ;bx = segment to realloc
  686.  
  687.         push    si
  688.         push    di
  689.         mov    cs:data_seg,ds
  690.         mov    cs:save_hi,dx
  691.         mov    cs:save_lo,ax
  692.  
  693.         or    bx,bx            ;is it a null pointer?
  694.         jz    @@MallocIt
  695.  
  696.         mov    cx,ax
  697.         or    cx,dx            ;does he want 0 bytes?
  698.         jz    @@FreeIt
  699.  
  700.         add    ax,UsedHeaderSize+15    ;add the header size and
  701.         adc    dx,0            ;force paragraph boundary
  702.                 mov     cl,4
  703.         shr    ax,cl
  704.         shl    dx,cl
  705.         or    ah,dl            ;ax = number of paragraphs
  706.  
  707.         mov    es,bx            ;es = segment to realloc
  708.         mov    cx,es:[bsize]        ;cx = current block size
  709.         cmp    cx,ax
  710.         jb    @@ExpandIt
  711.         ja    @@ShrinkIt
  712. @@NoChange:
  713.         mov    dx,bx
  714.         mov    ax,UsedHeaderSize
  715.         jmp    SHORT @@AllDone
  716. @@ShrinkIt:
  717.         call    ShrinkBlock
  718.         jmp    SHORT @@AllDone
  719. @@ExpandIt:
  720.         call    ExpandBlock
  721.         jmp    SHORT @@AllDone
  722. @@MallocIt:
  723.         push    dx
  724.         push    ax
  725.         call    _farmalloc
  726.         jmp    SHORT @@Cleanup
  727. @@FreeIt:
  728.         push    bx
  729.         push    ax            ;has a zero left over
  730.         call    _farfree
  731. @@Cleanup:
  732.         pop     di                      ;cleanup stack
  733.         pop     di
  734. @@AllDone:
  735.         mov    ds,cs:[data_seg]
  736.         pop    di
  737.         pop    si
  738.         pop    bp
  739.         ret
  740.         ENDP
  741.  
  742.                 ENDS
  743.         END
  744.