252 lines
6.7 KiB
NASM
252 lines
6.7 KiB
NASM
;
|
|
; Copyright (c) Mix Software 1988
|
|
;
|
|
; --------------------------------------------------
|
|
; _fmalloc - allocate from far heap
|
|
; if no memory available, allocate from near heap
|
|
; char far *_fmalloc(size)
|
|
; unsigned size;
|
|
; --------------------------------------------------
|
|
;
|
|
IDT _fmalloc
|
|
DEF _fmalloc
|
|
FREF falloc
|
|
FREF malloc
|
|
;
|
|
_fmalloc MOV SI,SP
|
|
PUSH [SI][%PARM1-2]
|
|
CALLFAR falloc
|
|
ADD SP,%2
|
|
MOV CX,DX
|
|
OR CX,AX
|
|
JNZ OK
|
|
MOV SI,SP
|
|
PUSH [SI][%PARM1-2]
|
|
CALLFAR malloc
|
|
ADD SP,%2
|
|
TEST AX,AX
|
|
JZ NULL
|
|
MOV DX,DS
|
|
OK RETSEG
|
|
NULL XOR DX,DX
|
|
RETSEG
|
|
END
|
|
;
|
|
; --------------------------------------------------
|
|
; _ffree - release from near or far heap
|
|
; void _ffree(ptr)
|
|
; char far *ptr;
|
|
; --------------------------------------------------
|
|
;
|
|
IDT _ffree
|
|
DEF _ffree
|
|
FREF ffree
|
|
FREF free
|
|
;
|
|
_ffree MOV SI,SP
|
|
MOV AX,[SI][%PARM2-2]
|
|
MOV CX,DS
|
|
CMP AX,CX
|
|
JZ NEAR
|
|
PUSH AX
|
|
PUSH [SI][%PARM1-2]
|
|
CALLFAR ffree
|
|
ADD SP,%4
|
|
RETSEG
|
|
NEAR PUSH [SI][%PARM1-2]
|
|
CALLFAR free
|
|
ADD SP,%2
|
|
RETSEG
|
|
END
|
|
;
|
|
; --------------------------------------------------
|
|
; _nmsize - return the size of a memory block
|
|
; unsigned _nmsize(ptr)
|
|
; char near *ptr;
|
|
; --------------------------------------------------
|
|
;
|
|
IDT _nmsize
|
|
DEF _nmsize
|
|
DEF _msize
|
|
;
|
|
_msize EQU $
|
|
_nmsize MOV SI,SP
|
|
MOV BX,[SI][%PARM1-2]
|
|
MOV AX,[BX][%-2] ; get size and allocated flag
|
|
AND AX,>FFFE
|
|
SUB AX,%2
|
|
RETSEG
|
|
END
|
|
;
|
|
; --------------------------------------------------
|
|
; _memavl - return the byte count of available memory
|
|
; unsigned _memavl()
|
|
; --------------------------------------------------
|
|
;
|
|
IDT _memavl
|
|
REF $$CURH
|
|
REF $$HMIN
|
|
REF $$HMAX
|
|
DEF _memavl
|
|
;
|
|
_memavl MOV AX,[$$HMAX]
|
|
SUB AX,[$$HMIN]
|
|
SUB AX,[$$CURH]
|
|
SUB AX,6
|
|
RETSEG
|
|
END
|
|
;
|
|
; --------------------------------------------------
|
|
; coreleft - return the byte count of available memory
|
|
; unsigned coreleft()
|
|
; --------------------------------------------------
|
|
;
|
|
IDT coreleft
|
|
REF $$CURH
|
|
REF $$HMIN
|
|
REF $$HMAX
|
|
DEF coreleft
|
|
;
|
|
coreleft MOV AX,[$$HMAX]
|
|
SUB AX,[$$HMIN]
|
|
SUB AX,[$$CURH]
|
|
SUB AX,6
|
|
RETSEG
|
|
END
|
|
;
|
|
; --------------------------------------------------
|
|
; _freect - return the number of items in heap
|
|
; unsigned _freect(size)
|
|
; unsigned size;
|
|
; --------------------------------------------------
|
|
;
|
|
IDT _freect
|
|
REF $$CURH
|
|
REF $$HMIN
|
|
REF $$HMAX
|
|
DEF _freect
|
|
;
|
|
_freect MOV AX,[$$HMAX]
|
|
SUB AX,[$$HMIN]
|
|
SUB AX,[$$CURH]
|
|
SUB AX,6
|
|
MOV BX,SP
|
|
MOV BX,[BX][%PARM1-2]
|
|
XOR DX,DX
|
|
TEST BX,BX
|
|
JZ EXIT
|
|
DIV BX
|
|
EXIT RETSEG
|
|
END
|
|
;
|
|
; --------------------------------------------------
|
|
; _expand - expand a block of memory without moving it
|
|
; _expand(ptr,size)
|
|
; char *ptr;
|
|
; unsigned size; /* requested new size */
|
|
; --------------------------------------------------
|
|
;
|
|
IDT _expand
|
|
DEF _expand
|
|
IF UPPER
|
|
DEF _EXPAND
|
|
ENDIF
|
|
REF $$FREE
|
|
REF $$CURH
|
|
REF $$MAXH
|
|
FREF free
|
|
;
|
|
_EXPAND EQU $
|
|
_expand PUSH BP
|
|
MOV BP,SP
|
|
MOV BX,[BP][%PARM1]
|
|
MOV CX,[BX][%-2] ; get size and allocated flag
|
|
TEST CX,>0001
|
|
JZ AVAIL
|
|
SUB CX,%3 ; remove flag and overhead
|
|
CMP CX,[BP][%PARM2]
|
|
JB EXPAND ; Make larger
|
|
;
|
|
; Try to shrink the block
|
|
; If shrink is by at least 6 bytes, create a new pointer
|
|
; and use free to release it.
|
|
;
|
|
SHRINK SUB CX,[BP][%PARM2]
|
|
NEG CX
|
|
AND CX,>FFFE ; Must be an even number
|
|
CMP CX,%6
|
|
JB FREEOK ; Not enough to free
|
|
SUB [BX][%-2],CX ; Remove from this block count
|
|
ADD BX,[BX][%-2] ; Point to end of block
|
|
DEC BX ; remove allocated flag
|
|
INC CX
|
|
MOV [BX][%-2],CX ; create allocated block header
|
|
PUSH BX
|
|
CALLFAR free
|
|
POP BX
|
|
MOV AX,[BP][%PARM1]
|
|
POP BP
|
|
RETSEG
|
|
;
|
|
; Try to expand the block.
|
|
; the next higher block must be free
|
|
;
|
|
EXPAND MOV SI,[$$FREE] ; Start of free list
|
|
MOV DX,SI
|
|
ADD BX,CX ; Point to next block header
|
|
SEARCH CMP SI,BX ; Found next block?
|
|
JZ FOUND
|
|
MOV SI,[SI][%2] ; Move to next free block
|
|
CMP SI,DX ; Full circuit?
|
|
JNZ SEARCH
|
|
JMPS NULLEXIT ; unable to expand
|
|
FOUND CMP [SI],6
|
|
JBE NULLEXIT ; protect anchor
|
|
MOV DI,[SI][%4] ; predecessor
|
|
MOV BX,[SI][%2] ; successor
|
|
MOV [DI][%2],BX
|
|
MOV [BX][%4],DI ; block linked out
|
|
MOV CX,[SI] ; length of the free block
|
|
ADD [$$CURH],CX
|
|
MOV AX,[$$CURH]
|
|
CMP AX,[$$MAXH]
|
|
JBE ADJUST
|
|
MOV [$$MAXH],AX
|
|
ADJUST MOV BX,[BP][%PARM1] ; merge block
|
|
ADD CX,[BX][%-2]
|
|
MOV [BX][%-2],CX ; Blocks are merged
|
|
SUB CX,%3
|
|
JMPS SHRINK ; Return the excess
|
|
;
|
|
; Block is free - it has therefore already become as large as
|
|
; possible. Check size to generate return value
|
|
;
|
|
AVAIL SUB CX,%2
|
|
CMP CX,[BP][%PARM2]
|
|
JAE FREEOK ; Large enough
|
|
NULLEXIT XOR AX,AX
|
|
POP BP
|
|
RETSEG
|
|
FREEOK MOV AX,BX
|
|
POP BP
|
|
RETSEG
|
|
END
|
|
;
|
|
; --------------------------------------------------
|
|
; heapsiz - return the byte count of available memory
|
|
; unsigned heapsiz()
|
|
; --------------------------------------------------
|
|
;
|
|
IDT heapsiz
|
|
REF $$CURH
|
|
REF $$HMIN
|
|
REF $$HMAX
|
|
DEF heapsiz
|
|
;
|
|
heapsiz MOV AX,[$$HMAX]
|
|
SUB AX,[$$HMIN]
|
|
SUB AX,[$$CURH]
|
|
SUB AX,6
|
|
RETSEG
|
|
END
|