⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 galloc.asm

📁 dos 1.0 其中包含quick basic源代码、内存管理himem emm386 发展历史
💻 ASM
📖 第 1 页 / 共 2 页
字号:
DoSearchCompact:	;* if search fails first time, compact and try again
	mov	plblFailSearch,kernelOffset DoSearchAddMemory
do_compact:
	push	bx
	call	gcompact		; End of arena.  Try compacting.
	pop	bx
;*	* now retry
	pop	ax
	pop	cx
	pop	bx
	jmp	short gsearch_again


; Subroutine to search for a free global object.  Called from within
; the global memory manager's critical section.
;
;   Inputs:	AX = allocations flags
;		BX = #paras
;		CX = owner field value
;		DS:DI = address of global arena information structure
;
;   Outputs:	AX = data address of block allocated or NULL
;		DX = allocation flags or size of largest free block if
;		     AX = 0
;		Z flag set if AX = zero
;
;   Destroys:	BX,CX,SI,ES
;

gsearch:
	mov	plblFailSearch,kernelOffset DoSearchCompact
gsearch_again:
	push	bx			;* save cpara
	push	cx			; Save owner
	push	ax			; Save flags
	add	bx,1			; Room for header (set flags for galign)
	call	galign			; Get requested size in DX
	mov	cx,[di].hi_count	; ES:DI is our arena pointer
	mov	es,[di].hi_first	; Assume fixed, start with first entry
	mov	bx,ga_next		; and search forwards along next links
	test	al,GA_ALLOCHIGH 	; Allocating from high memory?
	jz	gs1			; No, continue
	mov	es,[di].hi_last 	; Yes, start with last entry
	mov	bl,ga_prev		; and search backwards along prev links
gs1:	mov	es,es:[bx]		; Skip first or last block
aloop:
	cmp	ES:[di].ga_owner,di	; Is block free?
	je	afree			; Yes, see if it is big enough
	mov	si,ES:[di].ga_handle	; See if moveable
	cmp	bl,ga_next		; No, moving forward?
	jne	aloop1			; No, see if we should stop looking
	or	si,si
	jz	anext
	cmp	[si].he_count,bh
	jne	anext			; No, keep looking
	pop	ax
	push	ax
	test	al,GA_MOVEABLE		; Yes, is this a fixed request?
	jnz	anext			; No, keep looking
	mov	ax,es:[di].ga_size	; Yes, is this moveable block
	inc	ax			; big enough for the fixed space
	cmp	ax,dx			; needed?
	jb	anext			; No, keep looking
	push	dx
	mov	dx,ax			; Yes, try to find a place for the
	call	gfindfree		; moveable block
	pop	dx
	or	ax,ax			; Did we find a place?
	jz	anext			; No, keep looking
	push	es:[di].ga_prev 	; Where to pick up enumeration from
	mov	si,es			; SI = moveable block
	mov	es,ax			; ES = free block big enough for it
	call	gmovebusy		; Move moveable block out of the way
	pop	es
	jmp	short aloop		; Restart enumeration to find new free block
aloop1:
	cmp	ds:[di].gi_reserve,di	; Is there a reserved swap area?
	je	anext			; No, next block
	or	si,si			; Stop backwards scan if not moveable
	jz	anotfound
	test	es:[di].ga_flags,GA_DISCCODE	; ... or not discardable code
	jz	anotfound
	jmp	short anext		; Otherwise keep scanning backwards
afree:
	call	gcheckfree		; Yes, room for requested size?
	jae	afound			; Yes, exit search loop
	cmp	ds:[di].gi_reserve,di	; No, is the reserved swap area?
	je	anext			; No, next block
	cmp	bl,ga_prev		; Yes, are we allocating for code?
	je	anotfound		; Yes, then can only go in the first
					; free block.
anext:
	mov	es,ES:[bx]		; ES = address of next block
	loop	aloop			; Loop to next arena block if there

anotfound:
	jmp	[plblFailSearch]	;* jump to retry or fail

afound:
	mov	ax,es:[di].ga_size	; Use actual size of free block
	inc	ax
; Here when we have a block big enough.
;   ES:DI = address of block
;   AX = size of block, including header
;   DX = requested size, including header
;   BX = ga_prev if backwards search and ga_next if forwards search
;
	mov	cx,ax			; See how much extra space there is
	sub	cx,dx			; (found size - requested size)
	xor	si,si			; Assume nothing extra to free
	jcxz	aexit			; No, continue
	cmp	bl,ga_prev		; Yes, scanning forwards or backwards?
	je	abwd			; Backwards.
	mov	si,es			; Forwards.   Put extra space at end of
	add	si,dx			; free block
	call	gsplice 		; ES:DI = block we are allocating
	jmp	short aexit		; SI = block to mark as free
abwd:
	mov	si,ES:[di].ga_next	; Scanning backwards.  Put extra space
	sub	si,dx			; at beginning of free block.
	call	gsplice
	mov	es,si			; ES:DI = block we are allocating
	mov	si,ES:[di].ga_prev	; SI = block to mark as free

; Here with allocated block
;   AX = data address or zero if nothing allocated
;   ES:DI = address of block to mark as busy and zero init if requested
;   SI = address of block to mark as free
;
aexit:
	pop	dx			; Restore flags
	pop	ES:[di].ga_owner	; Mark this block as busy
	pop	ax			;* discard original size request
	mov	al,GA_SEGTYPE
	and	al,dl
	mov	ES:[di].ga_flags,al	; Store segment type bits

	mov	ax,es			; AX = address of client data
	inc	ax

	test	dl,GA_ZEROINIT		; Want it zeroed?
	jz	aexit1			; No, all done
	mov	cx,ES:[di].ga_next	; Yes, zero paragraphs
	dec	cx			; to end of this block
	mov	bx,ax			; from beginning of client data
	call	gzero			; zero them
aexit1:
	mov	es,si			; Free any extra space
	call	gmarkfree
	or	ax,ax
	ret				; Return AX points to client portion
					; of block allocated.

; Subroutine to mark a block as free, coalescing it with any free blocks
; before or after it.
;
;   Inputs:	ES:DI = block to mark as free.
;		DS:DI = address of global arena information structure
;
;   Outputs:	SI = zero if freed a fixed block.  For moveable blocks,
;		SI = handle table entry
;		ES:DI = block freed (may have been coelesced)
;		Updated hi_count field in global arena information structure
;
;   Destroys:	SI
;
gmarkfree:
	mov	si,es
	or	si,si
	jz	free4

	; Mark this block as free by clearing the owner field.
	mov	ES:[di].ga_owner,di	; Mark as free

	; Remember the handle value in DX, before setting to zero.
	push	dx
	xor	dx,dx
	xchg	ES:[di].ga_handle,dx

	; Try to coelesce with next block, if it is free
	push	ES:[di].ga_prev 	; save previous block
	mov	es,ES:[di].ga_next	; ES = next block
	cmp	ES:[di].ga_owner,di	; Is it free?
	jne	free2			; No, continue
	call	gjoin			; Yes, coelesce with block we are freeing
free2:
	pop	es			; ES = previous block
	cmp	ES:[di].ga_owner,di	; Is it free?
	jne	free3			; No, continue
	mov	es,ES:[di].ga_next	; Yes, coelesce with block we are freeing;
	call	gjoin
free3:
	mov	si,dx			; Return 0 or handle in SI
	pop	dx			; restore DX
	cmp	ES:[di].ga_owner,di	; Point to free block?
	je	free4			; Yes, done
	mov	es,ES:[di].ga_next	; No, leave ES pointing at free block
free4:
	or	si,si
	ret

; Subroutine to search for a free block that is big enough but does not
; encroach on the area reserved for code swapping.
;
;   Inputs:	ES:DI = address of existing block to start looking at
;		CX = #arena entries left to look at
;		BX = direction of search, ga_next or ga_prev
;		DX = #paragraphs needed
;		DS:DI = address of global arena information structure
;
;   Outputs:	AX = zero or address of free block that is big enough
;

gfindfree:
	push	es
	push	cx
gffloop:
	cmp	es:[di].ga_owner,di	; Free block?
	jne	gffnext 		; No, continue
	call	gcheckfree		; Yes, is it big enough?
	mov	ax,es
	jae	gffexit 		; Yes, return
	cmp	bl,ga_prev		; No, scanning backwards?
	je	gfffail 		; Yes, fail
gffnext:
	mov	es,es:[bx]		; next or previous block
	loop	gffloop
gfffail:
	xor	ax,ax			; No, return zero in AX
gffexit:
	pop	cx
	pop	es
	ret

; Subroutine to check the size of the passed free block against the passed
; desired size, making sure that the limitations of the code reserve area
; are not violated.
;
;   Inputs:	ES:DI = address of free block
;		DX = #paragraphs needed
;		DS:DI = address of global arena information structure
;
;   Outputs:	AX = apparent size of free block
;
;   Destroys:	SI
;

gcheckfree:
	mov	ax,es:[di].ga_size	; Compute size of free block
	inc	ax
	cmp	[di].gi_reserve,di	; Is there a code reserve area?
	je	gcftest 		; No, size okay
	test	byte ptr [di].gi_cmpflags,GA_DISCCODE
	jnz	gcftest 		; Discardable code not restricted
	push	es
	mov	es,es:[di].ga_next	; Go to block after free block
	cmp	es:[di].ga_sig,GA_ENDSIG    ; Is it the end of the arena?
	je	gcfrsrv 		; Yes, go enforce reserve area
	test	es:[di].ga_flags,GA_DISCCODE	; Is it a discardable code seg?
	jz	gcftest1		; No, test size
gcfrsrv:
	pop	es			; Yes, compute real available size
	mov	si,[di].hi_last 	; See if beginning of reserve area
	sub	si,[di].gi_reserve	; is above the end of the free block
	cmp	si,es:[di].ga_next
	jae	gcftest 		; Yes, return actual size of free block
	sub	si,es:[di].ga_next	; No, compute amount of overlap
	neg	si
	cmp	ax,si			; Is it more than what is free?
	jbe	gcfrsrv1		; Yes, then apparent size is zero
	sub	ax,si			; No, reduce apparent size of free block
	jmp	short gcftest		; Test size.
gcfrsrv1:
	xor	ax,ax			; Nothing left, set apparent size to 0
	jmp	short gcftest		; Test size.
gcftest1:
	pop	es
gcftest:
	cmp	ax,dx			; Return results of the comparison
	ret

SUBRS	ENDP

sEnd	KERNEL

	END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -