home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload
/
ShartewareOverload.cdr
/
windows
/
mlocal.zip
/
MLOCAL.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-03-16
|
23KB
|
644 lines
;------------------------------------------------------------------------------
; Multiple Local Heap Routines
; Dan Quigley 10-28-90
;------------------------------------------------------------------------------
;;;DEBUG EQU 1
IFDEF DEBUG
DebugOut MACRO st
push ds
push offset DGROUP:st
cCall OUTPUTDEBUGSTRING
ENDM
DebugBreak MACRO
;;; int 1
ENDM
ENDIF
.286 ; Enable 286 instruction set
;------------------------------------------------------------------------------
; Equates and structures
;------------------------------------------------------------------------------
jmps EQU <jmp short> ; Helper equates
bptr EQU <byte ptr>
wptr EQU <word ptr>
dwptr EQU <dword ptr>
HSIZE EQU 8192 ; initial heap size
K EQU 1024
CRLF EQU <13,10,0>
arena struc
handle dw ?
full db ?
arena ends
;------------------------------------------------------------------------------
; CMACRO Setup
;------------------------------------------------------------------------------
.xlist ; Suspend listing
?DF = 1 ; Don't generate default segs
?PLM = 1 ; Support Pascal calling
?WIN = 1 ; Support Windows
include cmacros.inc
include windows.inc
.list
;------------------------------------------------------------------------------
; Segment definitions
;------------------------------------------------------------------------------
createSeg MLOCAL_TEXT,CODE,PARA,PUBLIC,CODE ; Define code segment
createSeg _DATA,DATA,PARA,PUBLIC,DATA,DGROUP ; Define data segment
defGrp DGROUP,DATA ; Declare DGROUP
assumes DS,DATA ; Tell assembler where DS is
; to be referenced
;------------------------------------------------------------------------------
; Global variables
;------------------------------------------------------------------------------
sBegin DATA
FLHeap dw 0 ; Global Handle to Heap
FLHandle dw 0 ; Handle to Handle Table
FLSize dw 0 ; Size of Handle Table
FLOffset dw 0 ; start of handle table
FLSel dw 0 ; selector to handle table
FLEnd dw 0 ; end of handle table
IFDEF DEBUG
staticB MultFreeHeap,<'MultFreeHeap',CRLF>
staticB MultLocalAlloc,<'MultLocalAlloc',CRLF>
staticB MultLocalCompact,<'MultLocalCompact',CRLF>
staticB MultLocalFlags,<'MultFlags',CRLF>
staticB MultLocalFree,<'MultLocalFree',CRLF>
staticB MultLocalHandle,<'MultLocalHandle',CRLF>
staticB MultLocalInit,<'MultLocalInit',CRLF>
staticB MultLocalLock,<'MultLocalLock',CRLF>
staticB MultLocalReAlloc,<'MultLocalReAlloc',CRLF>
staticB MultLocalSize,<'MultLocalSize',CRLF>
staticB MultLocalUnlock,<'MultLocalUnlock',CRLF>
staticB FarLocalAlloc,<'FarLocalAlloc',CRLF>
staticB FarLocalCompact,<'FarLocalCompact',CRLF>
staticB FarLocalFree,<'FarLocalFree',CRLF>
staticB FarLocalInit,<'FarLocalInit',CRLF>
staticB SetDStoHeap,<'SetDStoHeap',CRLF>
ENDIF
sEnd DATA
;------------------------------------------------------------------------------
; External procedures
;------------------------------------------------------------------------------
externFP <GLOBALALLOC>
externFP <GLOBALFREE>
externFP <GLOBALLOCK>
externFP <GLOBALUNLOCK>
externFP <LOCALALLOC>
externFP <LOCALCOMPACT>
externFP <LOCALFLAGS>
externFP <LOCALFREE>
externFP <LOCALHANDLE>
externFP <LOCALINIT>
externFP <LOCALLOCK>
externFP <LOCALREALLOC>
externFP <LOCALSIZE>
externFP <LOCALUNLOCK>
externFP <OUTPUTDEBUGSTRING>
;------------------------------------------------------------------------------
; _TEXT starts here
;------------------------------------------------------------------------------
sBegin CODE
assumes CS,CODE ; Reference CS
;------------------------------------------------------------------------------
; MultLocalAlloc - Allocates memory from the designated heap
;
; Returns : AX = Handle
;------------------------------------------------------------------------------
cProc MultLocalAlloc,<PUBLIC,FAR>,<es,ds>
parmW hHeap
parmW wFlags
parmW wBytes
cBegin
IFDEF DEBUG
DebugOut MultLocalAlloc
DebugBreak
ENDIF
mov ax,hHeap
cmp ax,0
je MLAExit
mov ds,ax
cCall LocalAlloc <wFlags,wBytes>
MLAExit:
cEnd
;------------------------------------------------------------------------------
; MultLocalCompact - Compacts the designated heap
;
; Returns : the largest block of free memory
;------------------------------------------------------------------------------
cProc MultLocalCompact,<PUBLIC,FAR>,<es,ds>
parmW hHeap
parmW wMinFree
cBegin
IFDEF DEBUG
DebugOut MultLocalCompact
DebugBreak
ENDIF
mov ax,hHeap
cmp ax,0
je LCExit
mov ds,ax
cCall LocalCompact <wMinFree>
LCExit:
cEnd
;------------------------------------------------------------------------------
; MultLocalFlags - Returns the Allocation flags of a local memory object
;
; Returns :Allocation Flags
;------------------------------------------------------------------------------
cProc MultLocalFlags,<PUBLIC,FAR>,<ds>
parmW hHeap
parmW hMem
cBegin
IFDEF DEBUG
DebugOut MultLocalFlags
DebugBreak
ENDIF
mov ax,hHeap
cmp ax,0
je LFExit
mov ds,ax
cCall LocalFlags <hMem>
LFExit:
cEnd
;------------------------------------------------------------------------------
; MultLocalFree - Frees a local memory block from the designated heap
;
; Returns : NULL on success
;------------------------------------------------------------------------------
cProc MultLocalFree,<PUBLIC,FAR>,<ds>
parmW hHeap
parmW hMem
cBegin
IFDEF DEBUG
DebugOut MultLocalFree
DebugBreak
ENDIF
mov ax,hHeap
cmp ax,0
je MLFErr
mov ds,ax
cCall LocalFree <hMem>
jmps MLFExit
MLFErr: mov ax,-1
MLFExit:
cEnd
;------------------------------------------------------------------------------
; MultLocalHandle - Returns the handle of the address of a block
;
; Returns : HANDLE
;------------------------------------------------------------------------------
cProc MultLocalHandle,<PUBLIC,FAR>,<ds>
parmD dwAddress
cBegin
IFDEF DEBUG
DebugOut MultLocalHandle
DebugBreak
ENDIF
lds ax,dwAddress
cCall LocalHandle <ax>
cEnd
;------------------------------------------------------------------------------
; MultLocalInit - Allocates a 64k from the global heap and initializes it
;
; Returns : HANDLE on success
;------------------------------------------------------------------------------
cProc MultLocalInit,<PUBLIC,FAR>,<es,di,si>
parmW wSize
cBegin
IFDEF DEBUG
DebugOut MultLocalInit
DebugBreak
ENDIF
push (GMEM_MOVEABLE OR GMEM_ZEROINIT)
and wSize,0FFF0h ; round to 16 byte
mov ax,0
push ax ; high order word on stack first
push wSize ; then low order
cCall GlobalAlloc ; allocate the heap
cmp ax,0 ; success?
je MLIExit ; no then exit
cCall GlobalLock <ax> ; we need the selector rights
mov ax,dx
cmp ax,0
push ax ; yes save the handle for later
je MLIErr
push ax ; Global handle is in ax
push 0 ; beging at start of heap
mov ax,wSize ; wSize - 1 for heap length
dec ax
push ax
cCall LocalInit ; LocalInit locks the heap
cmp ax,0 ; did Init fail?
jne MLIOK ; no then we're done
MLIErr:
cCall GlobalFree ; handle is still on stack
mov ax,0
jmps MLIExit
MLIOK: pop ax ; return the handle
MLIExit:
cEnd
;------------------------------------------------------------------------------
; MultLocalLock - Locks a local memory block from the designated heap
;
; Returns : selector:offset in dx:ax
;------------------------------------------------------------------------------
cProc MultLocalLock,<PUBLIC,FAR>,<es,ds>
parmW hHeap
parmW hMem
cBegin
IFDEF DEBUG
DebugOut MultLocalLock
DebugBreak
ENDIF
mov dx,0 ; assume failure
mov ax,hHeap
cmp ax,0
je MLLExit
mov ds,ax
cCall LocalLock <hMem>
cmp ax,0
je MLLExit
mov dx,ds
MLLExit:
cEnd
;------------------------------------------------------------------------------
; MultLocalReAlloc - Changes the size of the local memory block
;
; Returns : Handle to
;------------------------------------------------------------------------------
cProc MultLocalReAlloc,<PUBLIC,FAR>,<es,ds>
parmW hHeap
parmW hMem
parmW wBytes
parmW wFlags
cBegin
IFDEF DEBUG
DebugOut MultLocalReAlloc
DebugBreak
ENDIF
mov ax,hHeap
cmp ax,0
je MLRExit
mov ds,ax
cCall LocalReAlloc <hMem, wBytes, wFlags>
MLRExit:
cEnd
;------------------------------------------------------------------------------
; MultLocalSize - Returns the size of the memory block
;
; Returns : Size in bytes
;------------------------------------------------------------------------------
cProc MultLocalSize,<PUBLIC,FAR>,<ds>
parmW hHeap
parmW hMem
cBegin
IFDEF DEBUG
DebugOut MultLocalSize
DebugBreak
ENDIF
mov ax,hHeap
cmp ax,0
je MLSExit
mov ds,ax
cCall LocalSize <hMem>
MLSExit:
cEnd
;------------------------------------------------------------------------------
; MultLocalUnlock - Unlocks an object in the designated heap
;
; Returns : Lock Count
;------------------------------------------------------------------------------
cProc MultLocalUnlock,<PUBLIC,FAR>,<es,ds>
parmW hHeap
parmW hMem
cBegin
IFDEF DEBUG
DebugOut MultLocalUnlock
DebugBreak
ENDIF
mov ax,hHeap
cmp ax,0
je MLUExit
mov ds,ax
cCall LocalUnlock <hMem>
MLUExit:
cEnd
;------------------------------------------------------------------------------
; MultFreeHeap - Free the Local Heap
;
; Returns : NULL on success - Heap on Failure
;------------------------------------------------------------------------------
cProc MultFreeHeap,<PUBLIC,FAR>
parmW hHeap
cBegin
IFDEF DEBUG
DebugOut MultFreeHeap
DebugBreak
ENDIF
mov ax,hHeap
cmp ax,0
je FLHExit
cCall GlobalUnlock <hHeap>
cCall GlobalFree <hHeap>
FLHExit:
cEnd
;------------------------------------------------------------------------------
; FarLocalInit - Initializes the FarLocal Heap Routines
;
; Returns : Success NonZero | Failure FALSE
;------------------------------------------------------------------------------
cProc FarLocalInit,<PUBLIC,FAR>,<di>
cBegin
IFDEF DEBUG
DebugOut FarLocalInit
DebugBreak
ENDIF
mov ax,1 ; Assume success
cmp FLHeap,0 ; Have we initialized before
jne FLIExit ; Yes, then exit
mov FLSize,HSIZE ; Start with a 8K heap
cCall MultLocalInit <FLSize> ; Initialize the handle table
cmp ax,0 ; failure?
je FLIExit ; then were hosed
mov FLHeap,ax ; save the handle
push ax
push (LMEM_MOVEABLE OR LMEM_ZEROINIT)
push (K * 6) ; start with 2K entries
cCall MultLocalAlloc
cmp ax,0 ; allocation succeed?
jne TableOK ; yes
CleanUp: cCall MultFreeHeap <FLHeap> ; clean up
mov FLHeap,0
jmps FLIExit ; and get out
TableOK: mov FLHandle,ax ; store the handle
cCall MultLocalLock <FLHeap,FLHandle>
cmp dx,0 ; if we cant lock it down
je CleanUp ; then exit
mov FLOffset,ax ; store offset
mov FLSel,dx ; store selector
add ax,FLSize ; add the offset with size
dec ax ; 0 referenced
mov FLEnd,ax ; store the table end
cCall MultLocalInit <FLSize> ; Initialize the first heap to 8K
les di,dwptr FLOffset
mov es:[di],ax ; store the handle
FLIExit:
cEnd
;------------------------------------------------------------------------------
; FarLocalAlloc - Allocates from the FarLocal Heap
;
; Returns : Success DD HANDLE | Failure FALSE
;------------------------------------------------------------------------------
cProc FarLocalAlloc,<PUBLIC,FAR>,<di,si>
parmW wFlags
parmW wSize
cBegin
IFDEF DEBUG
DebugOut FarLocalAlloc
DebugBreak
ENDIF
cCall FarLocalInit ; initialize arena
mov ax,0 ; assume failure
mov dx,0
tsearch: les di,dwptr FLOffset ; es:di to top of arena
mov cx,wSize ; cx gets desired size
search: cmp es:[di].full,ch ; is this arena entry full
jbe found_one ; no then try the allocation
next_entry: add di,3 ; get next arena entry
cmp di,FLEnd ; are we beyond our limit
jb search ; no, then continue walk
; yes then attempt to resize
; the arena
cCall MultLocalUnlock <FLHeap,FLHandle>
add FLSize,(K * 6) ; add another 2K entries
mov ax,(LMEM_MOVEABLE OR LMEM_ZEROINIT)
cCall MultLocalReAlloc <FLHeap,FLHandle,FLSize,ax>
cmp ax,0 ; did realloc fail?
je WeBeHosed ; yes, exit
cCall MultLocalLock <FLHeap,FLHandle>
mov FLOffset,ax ; store offset
mov FLSel,dx ; store selector
add ax,FLSize ; add the offset with size
dec ax ; 0 referenced
mov FLEnd,ax ; store the table end
jmps tsearch ; no, then start walk
;;; **** possible optimization: calulate and set di to new area
found_one: cmp es:[di].handle,0 ; has this heap been initialized
jne do_alloc ; yes, then try the allocation
alloc_new: cCall MultLocalInit <HSIZE> ; Initialize the next heap
cmp ax,0 ; Init fail?
je WeBeHosed ; yes, were hosed
mov es:[di].handle,ax ; Store the new handle
do_alloc: push es:[di].handle ; push heap handle
push wFlags ; push flags
push wSize ; then requested size
cCall MultLocalAlloc ; attempt allocation
cmp ax,0 ; did the alloc fail?
jne got_it ; no
mov cx,wSize ; cx gets desired size
cmp ch,0 ; is size < 255
jne size_ok ; no, then size ok
inc ch ; yes, then bump ch
size_ok: mov es:[di].full,ch ; full here so mark it
jmp next_entry ; go back and search for more
got_it: mov dx,es:[di].handle ; we have 4 byte handles
WeBeHosed:
cEnd
;------------------------------------------------------------------------------
; FarLocalFree - Frees objects from the FarLocal Heap
;
; Returns : Failure DD HANDLE | Success NULL
;------------------------------------------------------------------------------
cProc FarLocalFree,<PUBLIC,FAR>,<di,si>
parmD dwHandle
cBegin
IFDEF DEBUG
DebugOut FarLocalFree
DebugBreak
ENDIF
mov dx,1 ; assume failure
mov ax,wptr dwHandle + 2 ; get the heaps global handle
les di,dwptr FLOffset ; es:di to top of arena
tfsearch: cmp es:[di].handle,ax ; is this the right arena entry
je found_it ; yes
add di,3 ; get next arena entry
cmp di,FLEnd ; are we beyond our limit
jb tfsearch ; no, then continue walk
jmps fdone
found_it: mov dx,0 ; signal success finding heap
push ds ; save ds
lds si, dwHandle ; get the heap and handle
cCall LocalSize <si> ; ask for object size
push ax ; save size
cCall LocalFree <si> ; si has object handle
pop cx ; size via pop
pop ds ; restore ds
cmp ax,0 ; success
jne fdone ; no, then error
cmp es:[di].full,0 ; is this heap marked full?
je fdone ; no, then were done
add es:[di].full,ch ; add the freed size (256 byte granularity)
jnc fdone ; overflow?
mov es:[di].full,0 ; reset the full byte
fdone:
cEnd
;------------------------------------------------------------------------------
; FarLocalCompact - Compacts the FarLocal Heap
;
; Returns : VOID
;------------------------------------------------------------------------------
cProc FarLocalCompact,<PUBLIC,FAR>,<di>
cBegin
IFDEF DEBUG
DebugOut FarLocalCompact
DebugBreak
ENDIF
les di,dwptr FLOffset ; es:di to top of arena
tfcsearch: cmp es:[di].handle,0 ; arena entry?
je fcdone ; no then were done
mov ax,es:[di].handle
push ds ; change ds
mov ds,ax
mov cx,0FFFFh ; max compaction
cCall LocalCompact <cx> ; do the compaction
pop ds ; restore ds
cmp es:[di].full,ah ; last alloc < new size
jge noreset
mov es:[di].handle,0 ; reset the full count
noreset: add di,3 ; get next arena entry
cmp di,FLEnd ; are we beyond our limit
jb tfcsearch ; no, then continue walk
jmps fcdone
fcdone:
cEnd
;------------------------------------------------------------------------------
; SetDStoHeap - Sets DS to heap
;
; Returns : Old DS
;------------------------------------------------------------------------------
cProc SetDStoHeap,<PUBLIC,FAR>
parmW hHeap
cBegin
IFDEF DEBUG
DebugOut MultLocalUnlock
DebugBreak
ENDIF
mov ax,hHeap
cmp ax,0
je SDSExit
push ds
mov ds,ax
pop ax
SDSExit:
cEnd
sEnd CODE
END