nearheap.asm
上传用户:super_houu
上传日期:2008-09-21
资源大小:4099k
文件大小:31k
源码类别:

DVD

开发平台:

Others

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