📄 gmem.asm
字号:
;*
;* CW : Character Windows
;*
;*
TITLE GMEM - Register interface to global memory allocator
.xlist
include kernel.inc
include galloc.inc
.list
sBegin KERNEL
assumes CS,KERNEL
assumes DS,NOTHING ;* usually points to MOB
assumes SS,DATA
;* * low level procs
externNP <halloc,hfree,hdref> ; HANDLE.ASM
externNP <gsplice,gjoin,gzero> ; GALLOC.ASM
externNP <gsearch,gmarkfree,gcheckfree> ; GALLOC.ASM
externNP <gmovebusy,gcompact> ; GCOMPACT.ASM
externNP <gnotify> ; GINTERF.ASM
IFDEF REALLOC_FIXED
externNP <gfixedCompact> ; GFIXCOMP.ASM
ENDIF ; REALLOC_FIXED
PUBLIC galign, gdref, ghandle, galloc, grealloc
PUBLIC gfree, glock, gunlock
SUBRS PROC NEAR
; GALIGN - procedure to align the size request for a global item to
; the next high valid paragraph boundary.
;
; Input: BX = #paras
; Carry flag set if #paras overflowed.
;
; Output: DX = #paras aligned to next higher multiple of 4
;
galign: jc align1 ; Overflow occur?
lea dx,[bx+GA_ALIGN] ; No, add alignment amount
and dl,GA_MASK ; ...modulo alignment boundary
cmp dx,bx ; Test for overflow
jb align1 ; Yes, continue
ret
align1: mov dx,GA_MASK ; Return largest possible size
ret
; GDREF - procedure to dereference a global handle.
;
; Inputs: DX = handle
;
; Outputs: ES:DI = address of arena header
; AX = address of client data
; CH = lock count or zero for fixed objects
; SI = handle table entry address or zero for fixed objects
; Z flag set if NULL handle or AX = 0
;
gdref:
xor cx,cx ; Zero lock count
mov ax,dx ; Return handle if fixed object
test al,GA_FIXED ; Is it moveable?
jz dref3 ; Yes, go dereference handle
xor si,si ; Set SI to zero for fixed objects
dref1:
or ax,ax ; No, were we passed NULL?
jz dref2 ; Yes, then all done
mov bx,ax ; No, return ES:DI pointing
dec bx
mov es,bx ; ...to arena header
cmp ES:[di].ga_sig,GA_SIGNATURE ; Return error if, invalid sig.
jne dref4
cmp ES:[di].ga_handle,si ; Handle mismatch
jne dref4
cmp ES:[di].ga_owner,di ; or free block
je dref4
dref2: ; Otherwise return with Z flag clear
ret
dref3:
mov si,dx
call hdref ; Get true address in AX and lock count in CH
jnz dref1 ; Compute arena header if valid true address
mov bx,[si].he_address ; Return owner of discarded object
dref4: ; in BX
xor ax,ax
ret
;
; GHANDLE - procedure return the handle for a global segment.
;
; Inputs: AX = handle or segment address parameter
; DS:DI = master object segment address
;
; Outputs: AX = handle or zero if invalid segment address
; Z flag set if DX is zero. O.W. Z flag reset and
; BX = pointer to handle table entry
; CX = lock count and flags for moveable object
; DX = segment address or zero if discarded or invalid handle
; ES:DI = arena header of block
;
; Destroys: ES,BX
;
ghandle:
mov bx,ax ; Compute address of arena header
test bl,GA_FIXED ; Fixed?
jnz gh0 ; Yes, have segment address then
or bx,bx ; Null handle?
jz gh1 ; Yes, return null
test bl,2 ; Valid moveable handle?
jz gh1 ; No, return null
mov bx,ds:[di].hi_htable ; Get base of handle table
cmp ax,bx ; Handle pointer before it?
jbe gh1 ; Yes, return null
mov cx,ds:[bx].ht_count ; Get size of handle table
shl cx,1
shl cx,1
add bx,cx
cmp ax,bx ; Handle pointer after it?
jae gh1 ; Yes, return null
mov bx,ax
mov cx,word ptr [bx].he_flags
inc cx ; Free handle?
jz gh1 ; Yes, return null
dec cx
test cl,HE_DISCARDED ; No, discarded?
jnz gh3 ; Yes, then no segment address
mov ax,ds:[bx].he_address ; No, convert handle to
mov bx,ax ; segment address
gh0:
dec bx
cmp ds:[di].hi_first,bx ; Error if points outside arena
jae gh1
cmp ds:[di].hi_last,bx
jbe gh1
mov es,bx
cmp ES:[di].ga_sig,GA_SIGNATURE
jne gh1 ; Error if invalid signature byte
cmp ES:[di].ga_owner,di
je gh1 ; Error if free segment
mov bx,ES:[di].ga_handle ; Get back pointer to handle
or bx,bx
jz ghx ; Return seg parameter if not moveable
cmp DS:[bx].he_address,ax ; Does handle point to segment?
jne gh1 ; No, return error
gh0a:
mov cx,word ptr [bx].he_flags
errnz <2-he_flags>
errnz <3-he_count>
mov dx,ax ; Return segment address in DX
or dx,dx ; Clear Z flag
mov ax,bx ; Yes, return handle
ret ; Return
gh1: xor ax,ax
ghx: xor cx,cx
mov dx,ax
ret
gh3:
xor ax,ax
test cl,HE_SWAPPED ; Discarded, is it swapped?
jz gh0a ; No, return NULL
jmp short gh1 ;* all done
; GALLOC - procedure to allocate global memory.
;
; Inputs: AX = allocation flags
; BX = #paragraphs
; CX = owner field
; DS:DI = address of global heap info
;
; Outputs: AX = handle to object or zero
; BX = size of largest free block if AX = 0
; CX = AX
;
galloc:
or bx,bx ; Allocating zero size?
jnz ga1 ; No, continue
xchg ax,cx ; AX = owner, CX = flags
test cl,GA_MOVEABLE ; Yes, moveable?
jz gaerr ; No, return error (AX = 0)
push cx ; save flags
call halloc ; and allocate handle for owner
pop dx ; restore flags
jcxz gaerr ; Error return
or dh,HE_DISCARDED ; and mark as discarded
mov [bx].he_flags,dh ; Set handle flags
jmp short gax
gaerr1:
dec dx ; Free block if no available
mov es,dx ; handles.
call gmarkfree
gaerr:
xor dx,dx ; DX = 0 means NOT out of memory
xor ax,ax ; Return AX = 0 to indicate error
jmp short gax
ga1:
call gsearch ; Search for block big enough
jz gax ; Done, if couldn't get enough
test dl,GA_MOVEABLE ; Is this a moveable object?
jz gax ; No, all done
call halloc ; Yes, allocate handle for object in AX
jcxz gaerr1 ; No handles, free memory
mov si,[bx].he_address ; Store back link to handle in header
dec si
mov es,si
mov ES:[di].ga_handle,bx ; Mark as moveable block
mov [bx].he_flags,dh ; Save discard level in handle
gax:
mov cx,ax
ret
; GREALLOC - procedure to reallocate global memory object
;
; Inputs: AX = allocation flags
; BX = #paragraphs for new size
; CX = new owner field value
; DX = existing handle
; DS:DI = address of global heap info
;
; Outputs: AX = handle to object or zero
; DX = size of largest free block if AX = 0
; CX = AX
;
grealloc:
push bp
mov bp,sp
push ax
rflags EQU word ptr [bp-2]
push dx
h EQU word ptr [bp-4]
push cx
owner EQU word ptr [bp-6]
push bx
rsize EQU word ptr [bp-8]
call gdref
mov bx,rsize
jz racreate ; Do nothing with zero, free or discarded handles
or bx,bx ; Are we reallocing to zero length?
jnz raokay1 ; No, continue
jcxz radiscard ; No, is handle locked?
rafail:
xor ax,ax ; Yes, return failure
xor dx,dx
jmp raexit
radiscard: ; No, then try to discard the object
; Here to discard object, when reallocating to zero size. This
; feature is only enabled if the caller passes the moveable flag
test byte ptr rflags,GA_MOVEABLE ; Did they want to discard?
jz rafail ; No, then return failure.
mov al,GN_DISCARD ; AL = discard message code
xor cx,cx ; CX = discard level of 0 (means realloc)
mov bx,h ; BX = handle
push es
mov dx,es:[di].ga_owner ;* set owner for notify
call gnotify ;* notify that we are discarding
;* note : no return value
pop es
push ES:[di].ga_owner ; Save owner field
push ax
call gmarkfree ; Free client data
pop cx
jz rafixed ; Return NULL if freed a fixed block
mov [si].he_address,cx ; No, remember owner in handle table entry
or [si].he_flags,HE_DISCARDED ; ...and mark discarded
jmp short rasame1 ; Return original handle, except
; GlobalLock will now return null.
rafixed:
pop ax
xor ax,ax
jmp raexit
rasame1:
jmp short rasame
raokay1:
jmp short raokay
rafail0:
jmp rafail
racreate:
test cl,HE_DISCARDED ; Is this a discarded handle?
jz rafail0 ; No, return error
or bx,bx ; Are we reallocing to zero length?
jz rasame ; Yes, return handle as is.
mov ax,GA_MOVEABLE ; Reallocating a moveable object
or ax,rflags ; ...plus any flags from the caller
mov cl,[si].he_flags ; ...plus saved segment type bits
and cl,GA_SEGTYPE
or al,cl
or ah,cl
test al,GA_DISCCODE ; Discardable code segment?
jz ranotcode
or al,GA_ALLOCHIGH ; Yes, allocate high
ranotcode:
mov [di].gi_cmpflags,al ; Save flags for gcompact
mov cx,[si].he_owner ; Use previous owner
push si ; save handle
call gsearch ; Find block big enough
pop si ; restore existing handle
jz racreate1
xor [si].he_flags,HE_DISCARDED ; and mark as not discarded
mov [si].he_address,ax ; Set new client data address
mov ch,[si].he_flags ; Get handle flags
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -