📄 krun2.asm
字号:
;* * have previous allocation (hole) still in use, need to fixup
mov ax,es:[di].ga_newpara ;* need to save old holes starting pos
mov ds:[di].ga_newpara,ax ;*
;* * also setup pointer to first allocation
mov ax,es:[di].ga_next ;* Get the next pointer
mov ds:[di].ga_next,ax ;* set as our next pointer
mov es,ax ;* we need to set its previous pointer
mov es:[di].ga_prev,ax ;* links now setup
;* * calculate new size of hole
mov bx,ds ;* pointer to
sub ax,bx ;*
dec ax ;* new size
mov ds:[di].ga_size,ax ;*
jmp short free_unused_alloc
;* * No previous hole, we have the new end signature for now
no_hole_after_this_one:
mov ds:[di].ga_size,1 ;* assume it was an endsignature
mov ds:[di].ga_next,ds ;* point to ourself
;* * now lets free the unused segments.
free_unused_alloc:
mov es,dx ;* The allocation to delete
mov ah,49h
int 21h ;* deleted the allocation.
mov dx,ds ;* setup to continue
mov es,dx ;* es:di =>hole
cCall genter ;* DS:DI => mob
cmp es:[di].ga_sig,GA_ENDSIG
jnz free_010
mov ds:[di].hi_last,dx ;* now the last block
free_010:
sub ds:[di].hi_count,2 ;* remove old sentinal and free block
jmp short find_free_loop ;* continue to process
;*****************************
;* * Part of the allocation is still used. See if we are in our
;* * base, or in an extra allocated segment.
;* * we can find this out, by, scanning backward until we find
;* * a hole, or the beginning.
;* * es:0 => free, ds:0 => previous, dx:0 => end of group
part_is_used:
;* * convert the free block into either sentinal or hole
push ds ;* save previous pointer
mov ds,dx ;* End of allocation
mov bl,ds:[di].ga_sig ;* see if hole or endsiz
mov es:[di].ga_sig,bl ;* the signature
mov es:[di].ga_owner,-1
mov es:[di].ga_flags,0
cmp bl,GA_ENDSIG ;* end or hole?
jz piu_end_was_end ;* end was a end
;* * End was hole, need to setup size and pointer
mov ax,ds:[di].ga_newpara ;* need to save old holes starting pos
mov es:[di].ga_newpara,ax ;*
;* * also setup pointer to allocation
mov ax,ds:[di].ga_next ;* Get the next pointer
mov es:[di].ga_next,ax ;* set as our next pointer
mov ds,ax ;* we need to set its previous pointer
mov ds:[di].ga_prev,ax ;* links now setup
;* * calculate new size of hole
mov cx,es ;* pointer to
sub ax,cx ;*
dec ax ;* new size
mov es:[di].ga_size,ax ;*
jmp short piu_find_begin ;* find beginning of memory unit
;* * No previous hole, we have the new end signature for now
piu_end_was_end:
mov es:[di].ga_size,1 ;* assume it was an endsignature
mov es:[di].ga_next,es ;* point to ourself
;* * now lets find the beginning of the memory unit.
piu_find_begin:
pop ds ;* restore pointer to previous
piu_loop:
cmp ds:[di].ga_sig,GA_HOLE ;* do we have a hole
jz piu_endloop ;* We are processing hole segment
mov ax,ds ;* get previous pointer
cmp ax,ds:[di].ga_prev ;* see if beginning of memory
jz piu_endloop ;* we have processed the holes.
mov ds,ds:[di].ga_prev ;* still looking
jmp short piu_loop ;*
piu_endloop:
push ds ;* save starting point
cCall genter ;* get DS;DI => mob
;* * at the end of the heap MUST be a free block of a reasonably
;* * large size (the free block due to freeing all code)
assumes ds,NOTHING
dec ds:[di].hi_count ;* decrement the count
mov dx,es ;* dx = address of sentinal
cmp bl,GA_ENDSIG ;* see if we need to update last ptr
jnz piu_not_last
mov ds:[di].hi_last,dx ;* new last pointer
piu_not_last:
pop ds ;* restore first in block
cmp ds:[di].ga_sig,GA_HOLE ;* see if hole or orignal
jz piu_hole ;
;* * the part in use is from the original allocation
mov ax,psLom ;* 1 big block
jmp short piu_resize ;* goto resize the block
;* * was part that was added on
piu_hole:
mov ax,ds:[di].ga_newpara ;* get the starting segment
;* * now freeup the free part of the segment
piu_resize:
;* * now free up anything to DOS
mov es,ax
mov bx,dx ;*
sub bx,ax ;* size of new block (in para)
add bx,1+cparaRunShell ;* add slush (+1 to keep end sentinal)
mov ah,4ah ;* modify allocated memory
int 21h
;* * now setup to try to process any other blocks
mov dx,ds ;* save dx=end of group
mov es,dx ;*
jmp find_free_loop ;* see if anymore groups to process
;* * resume with smaller global heap
end_shrink:
pop ds
IFDEF DEBUG
call FAR PTR PrintGlobalHeap ;*!! look at heap on exit
ENDIF ;DEBUG
cEnd ShrinkGlobalHeap
;********** RestoreGlobalHeap **********
;* entry : n/a
;* * restore global heap after ShrinkGlobalHeap
;* exit : n/a
cProc RestoreGlobalHeap, <PUBLIC, NEAR, ATOMIC>, <DS, SI, DI>
cBegin RestoreGlobalHeap
assumes ds,DGROUP
;* * modify block to make as large as possible
;* * first see if we have fragmented memory. If so, reallocate
;* * only the top one (for now).
;*
push ds ;* save for now
cCall genter ;* DS:DI => mob
mov es,ds:[di].hi_last ;* Point to last segment
mov cx,ds:[di].hi_count ;* get count
pop ds ;* restore ds segment
rst_loop:
cmp es:[di].ga_sig,GA_HOLE ;* look for hole
jz rst_hole ;* found a hole segment
mov es,es:[di].ga_prev ;* nope, lets try the next one
loop rst_loop ;*
;* * if we got here, we have only one memory allocation
mov es,psLom ;* 1 big block
jmp short rst_try_1meg ;* lets try to get 1 meg
rst_hole:
;* * found a hole, get its segment number and try to expand
mov es,es:[di].ga_newpara ;* address of memory allocation
rst_try_1meg:
;* * now try to allocate 1 meg, such that we can find out how much we can get
mov bx,0ffffh ;* i want it all
mov ah,4ah
int 21h
IFDEF DEBUG
jc ok_we_asked_for_too_much
int 3 ;* we got 1MB ???
ok_we_asked_for_too_much:
ENDIF ;DEBUG
;* * now do it for real
mov ah,4ah
int 21h
IFDEF DEBUG
jnc ok_we_got_it_back
int 3 ;* we got 1MB ???
ok_we_got_it_back:
ENDIF ;DEBUG
;* * get address of new end sentinal
mov ax,es
mov cx,es ;* have cx save es
add ax,bx ;* ax = new end
;* * check to make sure we are within the useable limits
mov es,psLom
cmp ax,es:[psUseMax]
jb have_high_limit
;* * we must adjust our block size (free the rest to DOS)
;* * (not efficient -- clean up later)
mov bx,es:[psUseMax]
push bx ;* limit
sub bx,cx ;* size we will use
mov es,cx ;* we need our segment
mov ah,4AH
int 21h ;* modify memory size
pop ax
;* AssertEQ ax,es:[psUseMax]
have_high_limit:
mov es,cx ;* restore our seg
sub ax,GA_ALIGN ;* room for arena
and al,LOW(GA_MASK) ;* make even
mov ds,ax ;* es => new sentinal
assumes ds,NOTHING
;* * create new sentinal
xor bx,bx
mov ds:[bx].ga_sig,GA_ENDSIG
mov ds:[bx].ga_owner,-1 ;* sentinal
mov ds:[bx].ga_size,GA_ALIGN
mov ds:[bx].ga_flags,bl
mov ds:[bx].ga_handle,bx ;* no handle
mov ds:[bx].ga_next,ds ;* link to self
mov cx,ax ;* psNew
cCall genter ;* DS:DI => mob
cmp ax,ds:[bx].hi_last
je NoFreeMem ;* TSR Got us
xchg ax,ds:[bx].hi_last ;* set new last, get old
inc ds:[di].hi_count ;* adding free object
mov ds,ax
mov es,cx
mov es:[bx].ga_prev,ds ;* link to other free
IFDEF DEBUG
cmp ds:[bx].ga_sig,GA_ENDSIG
je ok_end_sig
int 3
ok_end_sig:
ENDIF ;DEBUG
sub cx,ax ;* psNew - psOld
sub cx,GA_ALIGN ;* less overhead
mov ds:[bx].ga_sig,GA_SIGNATURE
mov ds:[bx].ga_owner,bx ;* FREE !!!
mov ds:[bx].ga_flags,GA_MOVEABLE
mov ds:[bx].ga_size,cx ;* new size
mov ds:[bx].ga_next,es ;* point to new sentinal
NoFreeMem:
cEnd RestoreGlobalHeap
;*****************************************************************************
;********** CompactToUpperHeap **********
;* entry : n/a
;* * compact to upper heap
;* exit : n/a
;* * NOTE : this code must be fixed since it throws everything out.
cProc CompactToUpperHeap, <FAR,PUBLIC, ATOMIC>, <DS, SI, DI>
cBegin CompactToUpperHeap
assumes DS,DGROUP
;* * compact the heap (removing any free gaps) -- throw out code as well
mov es,pGlobalHeap
xor di,di
xor ax,ax ;* discarded !!!
;* setup to compact to upper heap
;* NOTE : kludge to get all code
xchg ax,es:[di].gi_reserve ;* get old reserve
push ax
xor ax,ax
cCall GlobalCompact,<ax, ax> ;* Just get biggest chunk.
mov es,pGlobalHeap
pop es:[di].gi_reserve ;* restore reserve size
cEnd CompactToUpperHeap
sEnd KERNEL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -