📄 galloc.asm
字号:
;*
;* COW : Character Oriented Windows
;*
;* galloc.asm : global memory allocation
TITLE GALLOC - Global memory allocator
.xlist
include kernel.inc
include galloc.inc
include pbi.inc
.list
;*****************************************************************************
sBegin BSS
assumes DS,DGROUP
staticW plblFailSearch,0 ;* label to jump to if compact fails
sEnd BSS
sBegin DATA
externW <psLom>
sEnd DATA
;*****************************************************************************
sBegin KERNEL
assumes CS,KERNEL
assumes DS,NOTHING ;* DS points to MOB usually
assumes SS,DGROUP
externNP <gcompact,gmovebusy> ;* gcompact.asm
externNP <galign> ;* ginterf.asm
externNP <UnbindAll> ;* ldtunk.asm
PUBLIC gsplice, gjoin, gzero, gsearch, gmarkfree, gfindfree, gcheckfree
PUBLIC DoSearchAddMemory
SUBRS PROC NEAR
; Subroutine to splice in a new block into the arena after an existing block
;
; Inputs: ES:DI = address of existing block
; SI = address of new block to add to arena after existing block
; DS:DI = address of global arena information structure
;
; Outputs: Updated size field for old and new block
; Updated hi_count field in global arena information structure
;
; Destroys: CX
;
gsplice:
inc [di].hi_count ; Adding new arena entry
push si ; save new
push es ; save old
mov cx,si ; save old.next
xchg ES:[di].ga_next,cx ; and old.next = new
mov es,cx
mov ES:[di].ga_prev,si ; [old old.next].prev = new
mov es,si
mov ES:[di].ga_next,cx ; new.next = old old.next
sub si,cx ; new.size = new.next - new - 1
neg si
dec si
mov ES:[di].ga_size,si
pop cx ; new.prev = old
mov ES:[di].ga_prev,cx
mov ES:[di].ga_owner,di ; Zero owner & handle fields
mov ES:[di].ga_handle,di
mov ES:[di].ga_sig,GA_SIGNATURE
mov es,cx ; ES = old
sub cx,ES:[di].ga_next ; old.size = old.next - old - 1
neg cx
dec cx
mov ES:[di].ga_size,cx
pop si ; Restore new
ret
; Subroutine to join two blocks together, by removing one
;
; Inputs: ES:DI = address of block to remove
; DS:DI = address of global arena information structure
;
; Outputs: ES:DI = address of block that pointed to the one removed, with
; update size field and next pointer.
; Updated hi_count field in global arena information structure
;
; Destroys: SI
;
gjoin:
dec [di].hi_count
mov si,ES:[di].ga_prev ; who points to this block
mov es,ES:[di].ga_next ; Get address of block after
mov ES:[di].ga_prev,si ; one we are removing.
push es ; Change it's back link
mov es,si
pop ES:[di].ga_next ; and change the forward link
sub si,ES:[di].ga_next ; Recompute size of block
neg si
dec si
mov ES:[di].ga_size,si
ret
; Subroutine to fill a block with zeros
;
; Inputs: BX = address of first paragraph to zero
; CX = address of last paragraph to zero
;
; Outputs: BX = 0
;
; Destroys: CX
;
gzero:
push ax
push di
push es
mov es,bx ; ES = destination
sub bx,cx ; BX = #para
neg bx
inc bx
zero1:
mov cx,1000h
cmp bx,cx
jae zero2
mov cx,bx
jcxz zero3
zero2:
sub bx,cx
shl cx,1
shl cx,1
shl cx,1
xor ax,ax
xor di,di
cld
rep stosw ; Zero it out
mov ax,es ; Move to next 64k block
add ah,10h
mov es,ax
jmp zero1
zero3:
pop es
pop di
pop ax
ret
;* * special trap routines for search failure
;* * We will first try to compact. Then we will try to allocate some
;* * Additonal memory. If This fails we will then try to trash som
;* * bound segments(for code). Finally we fail.
;* *
;* if we failed we will then try to allocate memory to add onto our
;* * We will get the largest free memory. If > predefined minimum
;* * to add, then we will try to add this new segment into our
;* * memory list. Note: we will continue trying to allocate memory
;* * Until we do not get a big enough chunk.
DoSearchFail: ;* if search fails second time, give up
pop ax
pop cx
pop bx
xor ax,ax ;* failure
ret
DoSearchUnBind:
;* * if after compacting we still don't have enough
;* * if compacting for a data request => give up (DoSearchFail)
;* * if compacting for code => unbind any segments and try again
pop ax
push ax ;* ax = flags
test al,GA_ALLOCHIGH ; Allocating from high memory?
jz DoSearchFail ;* give up for data
;* * still trying code (un-bind any bound segments)
cCall UnbindAll
mov plblFailSearch,kernelOffset DoSearchFail
jmp do_compact
DoSearchAddMemory:
IFDEF WINDOWS_OLD_APP
jmp DoSearchUnbind ;* We can't handle this case
ELSE ; !WINDOWS_OLD_APP
mov bx,0ffffh ; Try to allocate 1 meg?
mov ah,48h
int 21h
cmp bx,100h ; Add minimum of 4k
jc DoSearchUnbind ; Not enough try 3rd pass
mov ah,48h ; Now lets allocate it
int 21h ;
jc DoSearchUnbind ; Allocate now failed?
;;;;; for now we will only handle ones added to end of list.
; see if we insert new chunk at begining, ending, or in middle
cmp ax,[di].hi_first ; see if before current first block
jc DoSearchAddMemory ; New lowest block
cmp ax,[di].hi_last ; see if after highest
jc DoSearchAddMemory ; Tsr went away?
; New highest point - most probable case. We ran something that
; was a TSR. Now lets merge this memory in. We need to create a
; new End sentinal. As the last ax=start, bx=lenth in paragraphs
push ax ;* Save original paragraph number
test ax,GA_ALIGN ;* see if aligned right
jz ok_align ;* yes
mov cx,ax ;* save orignal size
add ax,GA_ALIGN
and ax,GA_MASK ;* new starting position
push ax
sub ax,cx ;* see the difference
sub bx,ax ;* now update count of bytes
pop ax ;* restore new starting position
ok_align:
mov cx,ss:psLom ;* Need to make sure in range
mov es,cx ;* Use segment register.
mov cx,ax ; Save start postion.
add ax,bx ;* ax = new end
;* * check to make sure we are within the useable limits
cmp ax,es:[psUseMax]
jb still_in_range ;* ok request
mov ax,es:[psUseMax]
Still_in_range:
sub ax,GA_ALIGN ;* Lets get right position
and al,LOW(GA_MASK) ;* make even
mov bx,ax ;* compute new free area added
sub bx,cx ;*
dec bx ;*
;* now lets create a header for new free memory segment
mov es,cx ;* setup segment.
mov es:[di].ga_sig,GA_SIGNATURE ;* data segment
mov es:[di].ga_owner,0 ;* Free memory
mov es:[di].ga_size,bx ;* How much free area added
mov es:[di].ga_flags,0
mov es:[di].ga_handle,di ;* no handle
mov es:[di].ga_next,ax ;* link to new sentinal
mov bx,[di].hi_last ;* Get old high mark.
mov es:[di].ga_prev,bx ;* Link to old sentinal
;* * create new sentinal
mov es,ax ;* setup new sentinal segment
mov es:[di].ga_sig,GA_ENDSIG
mov es:[di].ga_owner,-1 ;* sentinal
mov es:[di].ga_size,GA_ALIGN
mov es:[di].ga_flags,0
mov es:[di].ga_handle,di ;* no handle
mov es:[di].ga_next,es ;* link to self
mov es:[di].ga_prev,cx
;* * update Old sentinal to be ;* fixed block that cant move
xchg ax,[di].hi_last ;* Setup pointer to new last object
mov es,ax ;* now we need to modify header
mov es:[di].ga_sig,GA_HOLE ;* setup as a hole.
mov es:[di].ga_next,cx ;* Setup next pointer to new memory object
sub cx,ax ;* Setup size of hole.
dec cx ;*
mov es:[di].ga_size,cx ;* size of hole
pop es:[di].ga_newpara ;* put allocation seg paragraph number
;* * now add 2 to the number of items in the list
add [di].hi_count,2 ;* add new free list, and endsig
jmp short do_compact ; now compact using new memory
ENDIF ; WINDOWS_OLD_APP
;**********************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -