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

📄 fhinit.asm

📁 [随书类]Dos6.0源代码
💻 ASM
📖 第 1 页 / 共 5 页
字号:
	JB	FHRaiseBotAvail ;if available room less than max, jump
	MOV	AX,DX		;else use the maximum
FHRaiseBotAvail:
	ADD	b$FHDEnd.FHD_hData,AX ;adjust the bottom FH boundary

;	Raise the top of the near heap by AX paragraphs.

	SHL	AX,CL		;movement amount now in bytes (CL still 4)
	MOV	CX,AX		;new near heap ending offset is...
	ADD	CX,b$NH_last	;...adjusted by the amount
	MOV	AX,b$NH_first	;use present near heap starting offset
	CALL	B$NHMOV 	;raise the near heap top
	MOV	b$NH_last,CX	;update the near heap ending offset

cEnd

;***
; B$FHLowerBottom - lower bottom boundary of far heap. (DOS 3)
;
;Purpose:
;	Lower the bottom boundary of the far heap to allow the released
;	space to be used for far heap allocations. If the far heap
;	cannot be lowered by the requested amount, it is lowered the
;	maximum amount possible.  The top of the near heap is lowered
;	as necessary.
;Entry:
;	AX = number of paragraphs requested to lower.
;Exit:
;	None
;Uses:
;	AX
;Exceptions:
;	Fatal error due to near heap inconsistency.
;******************************************************************************

cProc	B$FHLowerBottom,<NEAR,PUBLIC>,<CX>
cBegin

;	First screen the request for unreasonable requests.  This includes
;	a request at or over 1000H paragraphs (64K bytes).

	TEST	AH,0F0H 	;test if request is 64K bytes or over
	JNZ	FHLowerBotMax	;if so, just try for maximum request

;	Convert the request to bytes and compute the new ending offset.
;	If the byte request is larger than the near heap ending offset,
;	then just try the maximum request.

	MOV	CL,4		;paragraph-to-byte shift is four...
	SHL	AX,CL		;shift to get bytes to lower near heap
	MOV	CX,b$NH_last	;get present ending offset of near heap
	SUB	CX,AX		;compute new ending offset in request
	JC	FHLowerBotMax	;if ending offset would be negative, then max

;	If this ending offset is before the current starting offset,
;	then just try maximum request.

	MOV	AX,b$NH_first	;get start of near heap for move operation
; Fix comparison order in CMP.
	CMP	CX,AX		;test if starting offset before computed ending
	JBE	FHLowerBotMax	;if so, just try for maximum room available

;	Try to lower the far heap by the request amount.

	CALL	B$NHMOV	;lower near heap to maximum size
	JNC	FHLowerBotDone	;if successful, jump to clean up and exit

;	If the near heap cannot be lowered by the requested amount,
;	lower it by the maximum amount possible.

FHLowerBotMax:
	MOV	AX,b$NH_first	;get the near heap starting offset
	XOR	CX,CX		;set offset for maximum release of near heap
	CALL	B$NHMOV 	;lower near heap to maximum size
;
; After the lowering, update the near heap ending offset variable, and compute
; the new start of the far heap, which is the immediately following paragraph.
;
FHLowerBotDone:
	MOV	b$NH_last,CX	; update new near heap ending offset
	XCHG	AX,CX		; [AX] = end of near heap
	MOV	CL,4		; [CL] = byte to para chift count
	ADD	AX,10H		; [AX] = end of near heap + 1 para
	RCR	AX,CL		
	AND	AH,01FH 	; [AX] = para dgroup offset of far heap
	MOV	CX,DS		
	ADD	AX,CX		; [AX] = absolute para far heap start
	MOV	b$FHDEnd.FHD_hData,AX ; Set the new far heap base

cEnd

;***
; B$FHRaiseTop - raise top boundary of far heap (DOS 3)
;
;Purpose:
;	Raise the top boundary of the far heap to allow the reclaimed
;	space to be used for far heap allocations.  If the far heap
;	cannot be raised by the requested amount, it is raised the
;	maximum amount possible.
;Entry:
;	AX = number of paragraphs requested to raise.
;Exit:
;	AX = number of paragraphs actually reclaimed.
;Uses:
;	None.
;Exceptions:
;	Fatal error due to far heap inconsistency.
;******************************************************************************

cProc	B$FHRaiseTop,<NEAR,PUBLIC>,<BX,ES>
cBegin

;	Calculate the paragraph increment from the current far heap
;	top to the theoretical maximum paragraph.  Attempt to reallocate
;	with the minimum of this value and the requested value.

	MOV	BX,b$FHDStart.FHD_hData ;get the top of the far heap
	NOT	BX		;invert for calculation 0FFFFH-FHTop
	CMP	AX,BX		;test for minimum of the two values
	JB	FHRaiseTopReq	;if request if less, then use it
	MOV	AX,BX		;use the calculated maximum value
FHRaiseTopReq:
	CALL	FHSetTop	;attempt to reset the far heap top

cEnd

;***
; B$FHLowerTop - lower top boundary of far heap (DOS 3)
;
;Purpose:
;	Lower the top boundary of the far heap to allow the released
;	space to be used for external allocations. If the far heap
;	cannot be lowered by the requested amount, it is lowered the
;	maximum amount possible.
;Entry:
;	AX = number of paragraphs requested to lower.
;Exit:
;	AX = number of paragraphs actually released.
;Uses:
;	None.
;Exceptions:
;	Fatal error due to far heap inconsistency.
;******************************************************************************

cProc	B$FHLowerTop,<NEAR,PUBLIC>,<BX,CX,DX,SI,DI,ES>
cBegin

;	First, compact the far heap and determine the size of the
;	unallocated space after compaction.

	MOV	CX,AX		;save requested allocation
	CALL	B$FHCompact	;compact - SI is next to last desc in list
	CALL	FHParaSize	;get unallocated size in AX

;	We will need to use the FHD_hData field from the descriptor pointed
;	to by SI, but the descriptor may move during B$FHLowerBottom.  So get
;	the seg value now.  (The descriptor may move but the data won't.)
	MOV	SI,[SI].FHD_hData ; get data seg of entry

;	Test if request can fit within the unallocated space left.
	;if enough, then branch to move heap

	CMP	CX,AX		;test request against unallocated space
	JBE	FHLowTopFit	;if enough, then branch to move heap

;	Compute the room still needed from the near heap and try to
;	obtain it.

	SUB	AX,CX		;subtract request size from unalloc space...
	NEG	AX		;...and negate to compute room needed
	CALL	B$FHLowerBottom ;try to lower far heap bottom AX paragraphs

;	Set up for far heap move.  Get present far heap starting
;	paragraph in BX.

FHLowTopFit:
	MOV	BX,SI		;segment of next to last entry is start

;	Compute new starting paragraph in DX.

	MOV	DX,BX		;start with present ending segment
	SUB	DX,CX		;subtract request size (size if full request)
	JB	FHLowMaxDown	;if wraparound, just use lower FH bound
	CMP	DX,b$FHDEnd.FHD_hData ;test if all memory requested released
	JA	FHLowTopFull	;if so, then jump to process full request
FHLowMaxDown:			
	MOV	DX,b$FHDEnd.FHD_hData ;set to partial request (end of heap)
FHLowTopFull:
;
; Check for the source and destination apara's to be the same. If they are, we
; didn't release anything, and needn't do more.
;
	XOR	AX,AX		; return value if no movement
	CMP	BX,DX		
	JZ	FHLowTopDone	; nothing to move, just quit.

;	Compute size of entire allocated far heap for move and perform
;	the move down in memory.

	MOV	AX,b$FHDStart.FHD_hData ;get starting segment of far heap
	SUB	AX,BX		;subtract ending segment for allocated size
	CALL	B$FHMove	;move far heap data to new location

;	Compute the actual distance moved.  Since the move was down,
;	this value is negative.  Set the far heap top to update the
;	descriptor and reallocate the DOS block to reflect the new
;	starting segment.

	MOV	AX,DX		;get new ending segment of far heap
	SUB	AX,BX		;subtract old ending segment to get distance
	CALL	FHSetTop	;reallocate the block to release the space

;	Adjust all allocated descriptors in the descriptor list to
;	reflect the far heap movement.

	XOR	BX,BX		;adjust all descriptors - lowest starting...
	MOV	DX,0FFFFH	;...and highest ending offset to adjust
	CALL	B$FHAdjDescSeg	;adjust all descriptor segments by AX

;	Negate the sense of the move to return a positive value.

	NEG	AX		;return positive paragraphs returned
FHLowTopDone:			

cEnd

;***
; B$FHByteSize - get size of unallocated entry after compaction (DOS 3)
;
;Purpose:
;	Return the size in bytes of the unallocated entry,
;	if present, after a far heap compaction is performed.
;Entry:
;	SI = DGROUP offset to next to last far heap descriptor in
;	     the descriptor list.  Returned by the far heap compaction
;	     routine B$FHCompact.
;Exit:
;	DX:AX = size in bytes of the unallocated entry.
;Uses:
;	None.
;Exceptions:
;	None.
;******************************************************************************

cProc	B$FHByteSize,<NEAR,PUBLIC>
cBegin

;	Get the entry size in paragraphs in AX and then convert to
;	bytes in DX:AX.

	CALL	FHParaSize	;get entry size in paragraphs
	MOV	DX,AX		;move into both registers
	MOV	CL,4		;shift count for lower word
	SHL	AX,CL		;compute low-word byte size
	MOV	CL,12		;shift count for upper word
	SHR	DX,CL		;compute high-word byte size

cEnd

;***
; FHParaSize - get size of unallocated entry after compaction (DOS 3)
;
;Purpose:
;	Return the size in paragraphs of the unallocated entry,
;	if present, after a far heap compaction is performed.
;Entry:
;	SI = DGROUP offset to next to last far heap descriptor in
;	     the descriptor list.  Returned by the far heap compaction
;	     routine B$FHCompact.
;Exit:
;	AX = size in paragraphs of the unallocated entry.
;Uses:
;	None.
;Exceptions:
;	None.
;******************************************************************************

cProc	FHParaSize,<NEAR>
cBegin

;	Size of entry is the difference between the segment values
;	of the next-to-last entry in the descriptor list and the
;	last entry.

	MOV	AX,[SI].FHD_hData ;get value of next-to-last entry
	SUB	AX,b$FHDEnd.FHD_hData ;subtract value of last entry

cEnd

;***
;B$FHSelect, B$FHSelectSI - Call a proc for each FH descriptor (DOS 3 & 5)
;
;Purpose:
;	Added as part of revision [11].
;	This routine is used to indirectly dispatch to a routine
;	for each FH descriptor.  The called routine takes specific
;	action for the descriptor and returns a flag stating whether
;	or not to deallocate the entry.
;Entry:
;	SI    = Address of descriptor to start with (B$FHSelectSI only)
;	AX    = Address of near routine to dispatch to
;	BX    = parameter passed/returned from dispatch routine
;	CX    = parameter passed/returned to dispatched routine
;Exit:
;	None.
;Uses:
;	Per Convention.
;Exceptions:
;	None.
;******************************************************************************
cProc	B$FHSelectSI,<NEAR,PUBLIC>,<SI>
cBegin
	JMP	SHORT FHSelect	;jmp to common code
cEnd	<nogen>

cProc	B$FHSelect,<PUBLIC,NEAR>,<SI>
cBegin
	MOV	SI,OFFSET DGROUP:b$FHDStart ;point to start of descriptor chain

FHSelect:
	PUSH	DI
	XCHG	AX,DI		;DI points to address of routine to call


SelectLoop:
	MOV	SI,[SI].FHD_pNext ;get ptr to next descriptor in chain
	CMP	SI,OFFSET DGROUP:b$FHDEnd ;test if final descriptor
	JZ	SelectDone	;brif so - finished

DbAssertRel	SI,NZ,-1,FH_TEXT,<FHSelect found pNext field containing 0FFFFH>



	CALL	DI		;call routine
	OR	AX,AX		;deallocate entry?
	JZ	SelectLoop	;brif not - get next descriptor
	PUSH	BX
	MOV	BX,SI
	cCall	B$FHDealloc	;deallocate entry
	POP	BX
	JMP	SHORT SelectLoop ;go get next descriptor
SelectDone:
	POP	DI
cEnd


;***
; B$FHAdjDesc,B$FHAdjDescSI - adjust a range of far heap descriptor (DOS 3 & 5)
;
;Purpose:
;	Added as part of revision [11].
;	To adjust selected far heap descriptors by adding a given
;	value to the pNext field in each descriptor.  The
;	selection is determined by the DGROUP offset of the
;	descriptor being in the specified range.  The static
;	starting and ending descriptors are never adjusted here.
;	These routines are used when Far Heap DESCRIPTORS are moved.
;Entry:
;	AX = adjustment value to the pNext field of each affected
;	     far heap descriptor.
;	BX = lower DGROUP offset of descriptor range, inclusive.
;	DX = upper DGROUP offset of descriptor range, exclusive.
;	SI = address of descriptor to start adjustment with.
;Exit:
;	None.
;Uses:
;	None.
;Exceptions:
;	None.
;******************************************************************************

cProc	B$FHAdjDescSI,<NEAR,PUBLIC>,<SI>
cBegin
	JMP	SHORT FHAdjDescCommon
cEnd	<nogen>

cProc	B$FHAdjDesc,<NEAR,PUBLIC>,<SI>
cBegin
	MOV	SI,OFFSET DGROUP:b$FHDStart ;Start with beginning of list

FHAdjDescCommon:
	XCHG	AX,CX		;CX = desc adjustment
	XOR	AX,AX		;no segment adjustment
	cCall	FHAdjDesc	;call common routine to adjust seg/desc
cEnd


;***
; B$FHAdjDescSeg,FHAdjDescSegSI - adjust a range of far heap descriptor segments (DOS 3)
;
;Purpose:
;	FHAdjDescSegSI added as part of revision [32].
;	Renamed and rewritten as part of revision [11].

⌨️ 快捷键说明

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