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

📄 fhinit.asm

📁 [随书类]Dos6.0源代码
💻 ASM
📖 第 1 页 / 共 5 页
字号:
	SUB	AX,BX		;compute amount of data to move
	MOV	DX,BX		;start of data - size needed = ...
	SUB	DX,CX		;... start of data destination
	cCall	B$FHMove	;move the data
	POP	AX		;recover increment needed
	POP	SI		;recover entry FHD

;	Data is moved, now update all .FHD_hData fields for owners of
;	the moved data.

	XOR	BX,BX		;adjust all descriptors
	MOV	DX,BX		;starting with the Entry FHD to the
	DEC	DX		;end of the descriptor chain
	NEG	AX		;make negative to move heap down
	cCall	FHAdjDescSegSI	;adjust the descriptors
	MOV	BX,SI		;[BX] = entry FHD
	SUB	[BX].FHD_cPara,AX ;update the size to reflect the allocation

RealcDone:
cEnd

;***
;B$FHDeallocFAR - far entrypoint for B$FHDealloc.
;
;Purpose:
;	Added with revision [75].
;	Far entrypoint for B$FHDealloc (called from LOADRTM segment).
;Entry:
;	Same as B$FHDealloc
;Exit:
;	Same as B$FHDealloc
;Uses:
;	Same as B$FHDealloc
;Exceptions:
;	Same as B$FHDealloc
;******************************************************************************
cProc	B$FHDeallocFAR,<FAR,PUBLIC>
cBegin
	CALL	B$FHDealloc
cEnd

;***
; B$FHDealloc - deallocate a far heap entry (DOS 3 & 5)
;
;Purpose:
;	Deallocate the far heap entry referenced by the given
;	far heap descriptor.
;Entry:
;	BX = far heap descriptor of entry to be deallocated
;Exit:
;	None.
;Uses:
;	None.
;Exceptions:
;	Fatal internal error if descriptor not in descriptor list.
;******************************************************************************

cProc	B$FHDealloc,<NEAR,PUBLIC>,<AX,SI>
cBegin

;	Determine the far heap descriptor preceding the one to
;	be deallocated using FHPrevDesc.  Remove the descriptor
;	to be deallocated from the descriptor list and then clear
;	the descriptor segment (FHD_hData).

	CALL	FHPrevDesc	;pointer to previous FHD is in SI
	MOV	AX,[BX].FHD_pNext ;get FHD after the one to be deallocated
	MOV	[SI].FHD_pNext,AX ;link this with the previous FHD


	MOV	[BX].FHD_hData,0 ;clear the deallocated FHD segment value

cEnd

;***
; FHPrevDesc, B$FHPrevDescSI - get previous descriptor in list (DOS 3 & 5)
;
;Purpose:
;	Given a far heap descriptor in the descriptor list,
;	determine its predecessor in the list.
;Entry:
;	BX = FHD offset of the far heap descriptor
;	SI = FHD offset of FHD to start search with (B$FHPrevDescSI only)
;Exit:
;	SI = FHD offset of the predecessor FHD to that pointed
;	     pointer by BX
;Uses:
;	None.
;Exceptions:
;	Fatal internal error if given FHD not in descriptor list.
;******************************************************************************

cProc	FHPrevDesc,<NEAR>
cBegin

	MOV	SI,OFFSET DGROUP:b$FHDStart ;get first FHD of the list
cEnd	<nogen> 		;fall into B$FHPrevDescSI

cProc	B$FHPrevDescSI,<NEAR,PUBLIC> 
cBegin				

FHPrevLoop:
	CMP	[SI].FHD_pNext,BX ;test if predecessor to entry FHD
	JE	FHPrevFound	;if found, then exit with SI set
	MOV	SI,[SI].FHD_pNext ;get the next FHD in the descriptor list
	CMP	SI,OFFSET DGROUP:b$FHDEnd ;test if final descriptor
	JNZ	FHPrevLoop	;if not, then loop to process next FHD
	JMP	SHORT FHPrevError ;fatal error if FHD not found
FHPrevFound:

cEnd

FHPrevError:
	JMP	B$ERR_FHC	;give far heap inconsistency error

;***
; B$FHCompact - compact the far heap (DOS 3 & 5)
;
;Purpose:
;	Compact the far heap entries to upper memory within the
;	far heap.
;	This routine is a nop for DOS 5.
;
;Entry:
;	None.
;Exit:
;	SI = DGROUP offset of the next to last far heap descriptor
;	     in the FHD list.
;Uses:
;	None.
;Exceptions:
;	Fatal internal error if far heap inconsistency.
;******************************************************************************

cProc	B$FHCompact,<NEAR,PUBLIC>,<AX,BX,CX,DX,DI,ES>
cBegin

	CALL	ShrinkHelp	; Kick the help system to release all

	call	CompressBufs	; compress the document buffers

;	SI is a pointer that traverses down the far heap descriptor
;	list starting at b$FHDStart.  DX points to the segment in the
;	compacted far heap space.

	MOV	SI,OFFSET DGROUP:b$FHDStart ;initialize the FHD list pointer
	MOV	DX,[SI].FHD_hDATA ;get segment pointer to compacted space

;	This loop is executed for each entry in the far heap.  SI points
;	to the descriptor in the list while BX points to the start of the
;	far heap entry referenced by the descriptor.

FHCompactLoop:
	MOV	BX,[SI].FHD_hData ;get segment referenced by descriptor at SI
	MOV	AX,[SI].FHD_cPara ;get the length of the far heap entry
	SUB	DX,AX		;compute entry start segment after compaction
	CMP	BX,DX		;test source and destination if movement needed
	JE	FHCompactSkip	;if no movement needed, just skip to next entry
	CALL	B$FHMove	;move the entry from BX:0 to DX:0
	MOV	[SI].FHD_hData,DX ;update descriptor with new entry segment
FHCompactSkip:

;	Save the descriptor pointer in AX in case of exit.  Check far heap
;	consistency by ensuring segments of adjacent descriptors in the list
;	are not increasing.  Advance SI to the next descriptor in the list
;	and, if not the last, loop to process it.

	MOV	AX,SI		;save the descriptor pointer
	MOV	SI,[SI].FHD_pNext ;point to next descriptor in the list
	CMP	[SI].FHD_hData,BX ;test if entry segments are not increasing
	JA	FHCompactError	;if not, then internal error
	CMP	SI,OFFSET DGROUP:b$FHDEnd ;test if last is reserved descriptor
	JNE	FHCompactLoop	;if not, process it

;	Finished with the compaction.  Check whether the last descriptor is
;	the special one reserved.  Set exit variable with next to last
;	descriptor in the list.  This is used to directly determine the size
;	and location of the unallocated space in the far heap.

	CMP	[SI].FHD_cPara,0 ;test if entry size is zero
	JNZ	FHCompactError	;if not, then internal error
	CMP	[SI].FHD_pNext,0 ;test if link field is zero
	JNZ	FHCompactError	;if not, then internal error
	MOV	SI,AX		;set exit variable to next to last descriptor

cEnd

FHCompactError:
	JMP	B$ERR_FHC	;give far heap inconsistency error


;***
; B$FHMove - move or clear a far heap region (DOS 3)
;
;Purpose:
;	Moves a far heap region either up or down within the far heap
;	or clears a far heap region to zeroes.	The region may consist
;	of one or more far heap entries, even the entire heap.
;
;Entry:
;	BX = starting segment of the far heap region to move
;	DX = destination segment of the far heap region
;	AX = size of region to move in paragraphs
;
;Exit:
;	if BX > DX, move AX paragraphs down from BX:0 to DX:0
;	if BX < DX, move AX paragraphs up from BX:0 to DX:0
;	if BX = DX, clear AX paragraphs from BX:0
;
;Uses:
;	AX, BX, CX, DX, DI, ES.
;Exceptions:
;	None.
;******************************************************************************

;	Since the repeated string move instruction (REP MOVSW) is used,
;	a memory region must be split into a number of 64K-byte
;	partitions followed by final partition of less than 64K bytes.
;
;	For moving a region down in memory, the lowest word in the
;	region is moved down first, followed by the next up to the
;	highest word in the region.  To implement this using the minimum
;	number of string move instructions, the first partition is defined
;	at the lower boundary of the region with any succeeding partitions
;	located 64K bytes (or 1000H paragraphs) higher in memory.  The
;	string moves are executed with the direction flag cleared (CLD).
;
;	For moving a region up in memory, the highest word in the
;	region is moved up first, followed by the next down to the lowest
;	word in the region.  The first partition is defined from the
;	upper boundary of the region with any succeeding partitions
;	located 64K bytes (or 1000H paragraphs) lower in memory.  The
;	the string moves are executed with the direction flag set (STD).
;
;	For clearing a region in memory, each partition is cleared
;	separately.  The partitions are defined from lowest word in the
;	region to the highest as in moving the region down.  The first
;	word of the partition is cleared and then a repeated string move
;	propagated the cleared word to the end of the partition.

cProc	B$FHMove,<PUBLIC,NEAR>,<SI,DS> 
cBegin

; Add assertion to check if FH is expected to be stable.
DbAssertRel	[B$FHStable],Z,0,FH_TEXT,<Attempted to relocate far heap when not expected to.>

;	On procedure entry, the direction flag is assumed cleared and BX
;	and DX point to the lower boundary of the region before and after
;	the move, respectively.  For moving down or clearing, BX and DX
;	also point to the start of the first partition to be moved or
;	cleared.

	CMP	BX,DX		;test if moving down or clearing region
	JAE	FHMoveLoop	;if so, then jump to start of partition loop

;	For moving up the direction flag must be set and BX and DX point
;	to the end of the region which is also the end of the first
;	partition.  They will be adjusted to the partition start before
;	the string move is done.

	STD			;set direction flag - moves go from high to low
	ADD	BX,AX		;source pointer at partition end
	ADD	DX,AX		;destination pointer at partition end

;	This loop is executed for each partition.  The size of the partition
;	in paragraphs is computed.  AX contains the number of paragraphs
;	left to process.

FHMoveLoop:
	MOV	CX,1000H	;get default size of partition
	CMP	CX,AX		;test if a full partition can be processed
	JB	FHNotLast	;if so, then jump to use the default size
	MOV	CX,AX		;othewise use the remaining paragraphs
FHNotLast:
	SUB	AX,CX		;update paragraphs left to process

;	If moving up, update the partition pointers in BX and DX to the
;	start of the next partition lower in memory.

	CMP	BX,DX		;test if moving entry up
	JAE	FHNotUpNext	;if not, jump to set segments
	SUB	BX,CX		;point to start of source partition
	SUB	DX,CX		;point to start of destination partition
FHNotUpNext:

;	Set segment registers in preparation to string move.

	MOV	DS,BX		;set the source segment register
	MOV	ES,DX		;set the destination segment register

;	If moving down or clearing, update the partition pointers in
;	BX and DX to start of the next partition up in memory.

	CMP	BX,DX		;test if moving down or clearing
	JB	FHNotDownNext	;if not, then jump to set the count
	ADD	BX,CX		;point to start of next source partition
	ADD	DX,CX		;point to start of next destination partition
FHNotDownNext:

;	Compute the word count for the string move.

	SHL	CX,1		;Paragraphs to words - shift once...
	SHL	CX,1		;...and twice...
	SHL	CX,1		;...and thrice for the word count

;	Compute the source offset.  If moving down or clearing, the offset
;	is zero.  If moving up, the offset is the byte offset of the last
;	word in the partition.

	XOR	SI,SI		;assume source offset is zero
	CMP	BX,DX		;test if moving entry up
	JAE	FHNotUpOffset	;if not, then use jump to use the zero offset
	MOV	SI,CX		;get the word count for partition
	DEC	SI		;make zero-relative word index
	SHL	SI,1		;shift to make byte offset of last word
FHNotUpOffset:

;	Compute the destination offset.  If moving up or down, it is the
;	same as the source offset.  If clearing, it is two more than the
;	source offset.	Clearing uses a string move to overlap an initial
;	zero word entry through the entire partition.

	MOV	DI,SI		;assume moving - destination same as source
	CMP	BX,DX		;test if clearing partition
	JNE	FHNotClear	;if not, then jump to perfrom string move
	MOV	[SI],SI 	;clear the first word of the partition
	INC	DI		;set destination pointer to...
	INC	DI		;the next word in the partition
	DEC	CX		;first word is already zero
FHNotClear:

;	Perform the string move.  If any more partitions, then loop to
;	process them.

	REP	MOVSW		;move or clear the partition
	OR	AX,AX		;test if more partitions to process
	JNZ	FHMoveLoop	;if so, then jump
	CLD			;clear the direction flag

cEnd

;***
; B$FHTestRaiseBottom - raise bottom only if below DGROUP end
; B$FHRaiseBottom - raise the bottom of the far heap (DOS 3)
;
;Purpose:
; Raise the bottom boundary of the far heap to allow the released space to be
; used for near heap allocations. The far heap is raised to maximize the near
; heap size.
;
;Entry:
; None.
;
;Exit:
; None.
;
;Uses:
; AX	  (B$FHTestRaiseBottom)
; None.
;
;Exceptions:
; None.
;
;******************************************************************************
cProc	B$FHTestRaiseBottom,<NEAR,PUBLIC> ; Important: no frame
cBegin				
	MOV	AX,DS		; [AX] = paragraph base of dgroup
	ADD	AH,10H		; [AX] = paragraph base of dgroup + 64k
	CMP	AX,b$FHDEnd.FHD_hData ; See if FH below end of DGROUP
	JA	B$FHRaiseBottom ; Jump if it is, see if can reclaim DGROUP
cEnd				

;  Make B$FHRaiseBottom be called by vector

cProc	B$FHRaiseBottom,<NEAR,PUBLIC>,<AX,BX,CX,DX,SI>
cBegin

;	Compute the paragraphs to raise the far heap to maximize the
;	near heap size.

	MOV	DX,0FFFEH	;get maximum DGROUP for near heap
	SUB	DX,b$NH_last	;subtract to get maximum amount to raise
	MOV	CL,4		;byte-to-paragraph shift count
	SHR	DX,CL		;compute maximum paragraphs to raise

;	Compute the paragraphs of free space in the far heap.

	CALL	B$FHCompact	;compact the far heap (SI = desc of top entry)
	CALL	FHParaSize	;get paragraphs of free space

;	Select the minimum of the two values to use to raise the far heap.

	CMP	AX,DX		;compare available room with maximum request

⌨️ 快捷键说明

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