home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / TRYHEAP.ZIP / HEAP.ASM next >
Assembly Source File  |  1989-03-15  |  13KB  |  389 lines

  1.         title   HEAP.ASM  Simple MASM Heap manager
  2.         page    55,132
  3.  
  4. ; HEAP.ASM --- Simple Heap Manager for MASM Programs
  5. ; Copyright (C) 1989 Ziff Davis Communications
  6. ; PC Magazine * Ray Duncan
  7. ;
  8. ; To trade safety for speed, change the CHKPTRS equate.
  9. ;
  10. ; The routines in this module all assume that the 
  11. ; CPU direction flag is clear!!
  12.  
  13. true    equ     -1
  14. false   equ     0
  15.  
  16. chkptrs equ     true                    ; if true, HREALLOC and 
  17.                                         ; HFREE check all pointers
  18.  
  19. DGROUP  group   _DATA
  20.  
  21. _DATA   segment word public 'DATA'
  22.  
  23. hbase   dw      0                       ; base address of heap
  24. hsize   dw      0                       ; size of heap
  25.  
  26. _DATA   ends
  27.  
  28.  
  29. _TEXT   segment word public 'CODE'
  30.  
  31.         assume  cs:_TEXT,ds:DGROUP
  32.  
  33. ;
  34. ; HINIT:        initialize local heap
  35. ; Call with:    AX      = size in bytes
  36. ;               DS:BX   = address of heap base
  37. ;
  38. ; Returns:      If function successful,
  39. ;               Carry   = clear
  40. ;
  41. ;               If function failed
  42. ;               Carry   = set
  43. ;
  44.         public  hinit
  45. hinit   proc    near
  46.  
  47.         cmp     ax,2                    ; check heap size
  48.         jbe     hinit1                  ; too small, return error
  49.         cmp     ax,32768
  50.         jae     hinit1                  ; too big, return error
  51.  
  52.         push    ax                      ; save registers
  53.         push    bx
  54.  
  55.         mov     hsize,ax                ; save heap size
  56.         mov     hbase,bx                ; save heap base address
  57.         sub     ax,2                    ; create header for block
  58.         mov     [bx],ax                 ; containing all free space
  59.         inc     ax
  60.         add     bx,ax                   ; set Carry if segment wrap
  61.  
  62.         pop     bx                      ; restore registers     
  63.         pop     ax
  64.         ret                             ; return to caller
  65.  
  66. hinit1: stc                             ; bad parameter,
  67.         ret                             ; return Carry = set
  68.  
  69. hinit   endp
  70.  
  71. ;
  72. ; HALLOC:       allocate block from local heap
  73. ;
  74. ; Call with:    AX      = requested block size
  75. ;
  76. ; Returns:      If function successful
  77. ;               Carry   = clear
  78. ;               DS:BX   = address of allocated block
  79. ;
  80. ;               If function unsuccessful
  81. ;               Carry   = set
  82. ;
  83.         public  halloc
  84. halloc  proc    near
  85.  
  86.         call    hfind                   ; try and allocate block
  87.         jnc     hal1                    ; jump if block was found
  88.  
  89.         call    hcoal                   ; coalesce free blocks
  90.         call    hfind                   ; try again to allocate
  91.  
  92. hal1:   ret                             ; return to caller
  93.  
  94. halloc  endp
  95.  
  96. ;
  97. ; HREALLOC:     resize previously allocated block
  98. ;
  99. ; Call with:    AX      = new requested block size
  100. ;               DS:BX   = address of existing block
  101. ;
  102. ; Returns:      If function successful
  103. ;               Carry   = clear
  104. ;               DS:BX   = address of resized block
  105. ;
  106. ;               If function unsuccessful
  107. ;               Carry   = set
  108. ;
  109.         public  hrealloc
  110. hrealloc proc   near
  111.  
  112.         push    ax                      ; save registers
  113.         push    cx
  114.         push    si
  115.         push    di
  116.         push    es
  117.  
  118.         if      chkptrs
  119.         call    hvalid                  ; check if valid pointer
  120.         jnc     hreal1                  ; pointer is OK
  121.         jmp     hreal6                  ; bad pointer, exit
  122.         endif
  123.  
  124. hreal1: mov     cx,ax                   ; save new requested size
  125.         mov     si,bx                   ; save block base address
  126.         mov     di,hbase                ; get address of heap end
  127.         add     di,hsize
  128.  
  129.         mov     ax,[si-2]               ; get current block size
  130.         and     ax,7fffh                ; remove in-use bit
  131.         cmp     cx,ax                   ; is block growing?
  132.         ja      hreal2                  ; yes, jump
  133.         je      hreal5                  ; no size change, exit
  134.  
  135.         sub     ax,cx                   ; block shrinking, find excess
  136.         cmp     ax,2                    ; enough for another header?
  137.         jb      hreal5                  ; no, leave block alone
  138.  
  139.         mov     [si-2],cx               ; shrink existing block
  140.         or      word ptr [si-2],8000h   ; and set in-use bit
  141.         add     si,cx                   ; create new block to hold
  142.         sub     ax,2                    ; the excess memory
  143.         mov     [si],ax
  144.         jmp     hreal5                  ; now exit
  145.  
  146. hreal2: call    hcoal                   ; coalesce free blocks
  147.  
  148.         add     si,ax                   ; get addr. of next block
  149.         cmp     si,di                   ; reached end of heap?
  150.         je      hreal4                  ; yes, jump
  151.  
  152.         test    word ptr [si],8000h     ; next block free?
  153.         jnz     hreal4                  ; no, must try elsewhere
  154.         add     ax,[si]                 ; yes, are combined blocks
  155.         add     ax,2                    ; large enough?
  156.         cmp     cx,ax
  157.         ja      hreal4                  ; no, jump
  158.  
  159.         mov     [bx-2],cx               ; update block header and
  160.         or      word ptr [bx-2],8000h   ; set in-use flag
  161.  
  162.         sub     ax,cx                   ; find excess memory
  163.         cmp     ax,2                    ; large enough for header?
  164.         jb      hreal3                  ; no, jump
  165.  
  166.         mov     si,bx                   ; create header for block
  167.         add     si,cx                   ; containing excess memory
  168.         sub     ax,2
  169.         mov     [si],ax
  170.         jmp     hreal5                  ; now exit
  171.  
  172. hreal3: add     ax,cx                   ; excess is 0 or 1 bytes,
  173.         mov     [bx-2],ax               ; fold it into the block
  174.         or      word ptr [bx-2],8000h
  175.         jmp     hreal5                  ; now exit
  176.  
  177. hreal4: mov     ax,cx                   ; look elsewhere for
  178.         mov     si,bx                   ; sufficiently large block
  179.         call    hfind
  180.         jc      hreal6                  ; none available, exit
  181.  
  182.         and     word ptr [si-2],7fffh   ; mark old block available
  183.         mov     cx,[si-2]               ; get its length for move
  184.         mov     di,bx                   ; copy old block to new
  185.         push    ds
  186.         pop     es
  187.         rep movsb
  188.  
  189. hreal5: clc                             ; successful reallocation,
  190.                                         ; return Carry = clear
  191.  
  192. hreal6: pop     es                      ; restore registers
  193.         pop     di
  194.         pop     si
  195.         pop     cx
  196.         pop     ax
  197.         ret                             ; return to caller
  198.  
  199. hrealloc endp
  200.  
  201. ;
  202. ; HFREE:        release heap block
  203. ; Call with:    DS:BX   = block pointer
  204. ;
  205. ; Returns:      If CHKPTRS is FALSE
  206. ;               Nothing
  207. ;
  208. ;               If CHKPTRS is TRUE and pointer valid
  209. ;               Carry   = clear
  210. ;
  211. ;               If CHKPTRS is TRUE and pointer invalid
  212. ;               Carry   = set
  213. ;
  214.         public  hfree
  215. hfree   proc    near
  216.  
  217.         if      chkptrs
  218.         call    hvalid                  ; check if valid pointer
  219.         jc      hfree1                  ; jump if bad pointer
  220.         endif
  221.  
  222.         and     word ptr [bx-2],07fffh  ; turn off in-use flag
  223. hfree1: ret                             ; back to caller
  224.  
  225. hfree   endp
  226.  
  227. ;
  228. ; HFIND:        private subroutine for HALLOC and HREALLOC,
  229. ;               finds a free block in heap
  230. ;
  231. ; Call with:    AX      = requested block size
  232. ;
  233. ; Returns:      If function successful
  234. ;               Carry   = clear
  235. ;               DS:BX   = address of allocated block
  236. ;
  237. ;               If function unsuccessful
  238. ;               Carry   = set
  239. ;               
  240. hfind   proc    near
  241.  
  242.         push    ax                      ; save registers
  243.         push    cx
  244.         push    si
  245.         push    di
  246.  
  247.         mov     cx,ax                   ; save requested block size
  248.         mov     si,hbase                ; get heap base address
  249.         mov     di,si
  250.         add     di,hsize                ; get address of heap end
  251.         
  252. hfind1: lodsw                           ; pick up next block header
  253.         or      ax,ax                   ; this block free?
  254.         js      hfind2                  ; not free if bit 15 set, jump
  255.         cmp     ax,cx                   ; block free, large enough?
  256.         jae     hfind4                  ; size is adequate, jump
  257.  
  258. hfind2: and     ax,07fffh               ; go to next block
  259.         add     si,ax
  260.         cmp     si,di                   ; end of heap reached?
  261.         jne     hfind1                  ; not yet, try next block
  262.  
  263. hfind3: stc                             ; couldn't allocate block,
  264.         jmp     hfind7                  ; return Carry = set
  265.  
  266. hfind4: mov     bx,si                   ; save block base in BX
  267.         je      hfind6                  ; jump if exactly right size
  268.  
  269.         sub     ax,cx                   ; find excess amount
  270.         cmp     ax,2                    ; enough for another header?
  271.         jae     hfind5                  ; yes, jump
  272.  
  273.         add     ax,cx                   ; no, skip this block
  274.         jmp     hfind2
  275.  
  276. hfind5: add     si,cx                   ; subdivide existing block
  277.         sub     ax,2                    ; create header for free block
  278.         mov     [si],ax                 ; containing excess memory
  279.         
  280. hfind6: or      cx,8000h                ; set block size and in-use
  281.         mov     [bx-2],cx               ; flag, also clear Carry
  282.  
  283. hfind7: pop     di                      ; restore registers
  284.         pop     si
  285.         pop     cx
  286.         pop     ax                       
  287.         ret                             ; return to caller 
  288.  
  289. hfind   endp
  290.  
  291. ;
  292. ; HCOAL:        private subroutine for HALLOC and HREALLOC,
  293. ;               coalesces adjacent free blocks in heap
  294. ;
  295. ; Call with:    nothing
  296. ;
  297. ; Returns:      nothing
  298. ;
  299. hcoal   proc    near
  300.  
  301.         push    ax                      ; save registers
  302.         push    bx
  303.         push    si
  304.         push    di
  305.  
  306.         mov     bx,hbase                ; get heap base address
  307.         mov     di,bx
  308.         add     di,hsize                ; get heap end address
  309.         
  310. hcoal1: mov     si,bx                   ; point to block header
  311.  
  312. hcoal2: lodsw                           ; get length from header
  313.         mov     bx,ax                   ; calc. address of next block
  314.         and     bx,7fffh
  315.         add     bx,si
  316.         cmp     bx,di                   ; end of heap reached?
  317.         je      hcoal3                  ; yes, exit
  318.  
  319.         or      ax,ax                   ; not last block, is it free?
  320.         js      hcoal1                  ; not free if bit 15 set, jump
  321.  
  322.         test    word ptr [bx],8000h     ; next block free also?
  323.         jnz     hcoal1                  ; no, jump
  324.  
  325.         add     ax,[bx]                 ; merge two blocks together
  326.         add     ax,2
  327.         sub     si,2
  328.         mov     [si],ax                 ; update header of 1st block
  329.         jmp     hcoal2                  ; try for another merge
  330.  
  331. hcoal3: pop     di                      ; restore registers
  332.         pop     si
  333.         pop     bx
  334.         pop     ax
  335.         ret                             ; return to caller
  336.  
  337. hcoal   endp
  338.  
  339.         if      chkptrs
  340. ;
  341. ; HVALID:       tests whether a heap pointer is valid
  342. ;
  343. ; Call with:    DS:BX   = questionable pointer to block
  344. ;
  345. ; Returns:      If pointer is valid
  346. ;               Carry   = clear
  347. ;
  348. ;               If pointer is invalid
  349. ;               Carry   = set
  350. ;               
  351.         public  hvalid
  352. hvalid  proc    near
  353.  
  354.         push    ax                      ; save registers
  355.         push    si
  356.         push    di
  357.  
  358.         test    word ptr [bx-2],8000h   ; make sure already allocated
  359.         je      hval2                   ; no, pointer invalid
  360.  
  361.         mov     si,hbase                ; get heap base address
  362.         mov     di,si
  363.         add     di,hsize                ; get heap end address
  364.  
  365. hval1:  lodsw                           ; get length of this block
  366.         cmp     si,bx                   ; do pointers match?
  367.         je      hval3                   ; yes, jump (carry is clear)
  368.         and     ax,7fffh                ; strip in-use bit and
  369.         add     si,ax                   ; advance to next block
  370.         cmp     si,di                   ; end of heap?
  371.         jne     hval1                   ; no, try again
  372. hval2:  stc                             ; end of heap, pointer invalid
  373.  
  374. hval3:  pop     di                      ; restore registers
  375.         pop     si
  376.         pop     ax
  377.         ret                             ; return to caller
  378.  
  379. hvalid  endp
  380.         endif
  381.  
  382. _TEXT   ends
  383.  
  384.         end
  385.  
  386.  
  387.