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

📄 fhinit.asm

📁 [随书类]Dos6.0源代码
💻 ASM
📖 第 1 页 / 共 5 页
字号:
;	To adjust selected far heap descriptors by adding a given
;	value to the segment value 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.
;	This routine is used when Far Heap DATA is moved.
;Entry:
;	AX = adjustment value to the segment of each affected
;	     far heap descriptor.
;	BX = lower DGROUP offset of descriptor range, inclusive.
;	DX = upper DGROUP offset of descriptor range, exclusive.
;	SI = descriptor to start adjustments with (FHAdjDescSegSI only)
;Exit:
;	None.
;Uses:
;	None.
;Exceptions:
;	None.
;******************************************************************************

cProc	FHAdjDescSegSI,<NEAR>,<SI>
cBegin
	JMP	SHORT AdjDescSegCommon
cEnd	<nogen>

cProc	B$FHAdjDescSeg,<NEAR,PUBLIC>,<SI>
cBegin
	MOV	SI,b$FHDStart.FHD_pNext ;[16]start with second FH desc in list

AdjDescSegCommon:		
	XOR	CX,CX		;No adjustment for pNext field
	cCall	FHAdjDesc	;common routine to adjust seg/descriptor
cEnd


;***
; FHAdjDesc - adjust a range of far heap descriptors (DOS 3 & 5)
;
;Purpose:
;	Added as part of revision [11].
;	To adjust selected far heap descriptors by adding a given
;	value to the segment value and/or 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.
;	This routine is used when Far Heap DATA and or Far Heap
;	descriptors are moved.
;Entry:
;	AX = adjustment value to the segment of each affected
;	     far heap descriptor.
;	CX = 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 = ptr to FHD to start search with.
;Exit:
;	None.
;Uses:
;	None.
;Exceptions:
;	None.
;******************************************************************************

cProc	FHAdjDesc,<NEAR,PUBLIC>,<SI,DI>
cBegin

;	Using SI, traverse the descriptor list until the ending of the
;	descriptor list is reached.

	MOV	DI,SI		;fall into loop

FHAdjDescLoop:
	MOV	SI,DI		;[SI] = current desc location
	MOV	DI,[SI].FHD_pNext ;[DI] = next descriptor in the list
	OR	DI,DI		;test if end of descriptor list
	JZ	FHAdjDescDone	;if so, then done

DbAssertRel	DI,NZ,-1,FH_TEXT,<FHAdjDesc found a pNext field containing 0FFFFH>

;	For each descriptor, adjust if in the specified range.

	CMP	DI,BX		;test against lower range, inclusive
	JB	FHAdjDescLoop	;if less, then loop for next
	CMP	DI,DX		;test against upper range, exclusive
	JAE	FHAdjDescLoop	;if more or equal, then loop for next
	ADD	[SI].FHD_hData,AX ;in range - adjust FH segment
	ADD	[SI].FHD_pNext,CX ;in range - adjust FH desc list
	JMP	SHORT FHAdjDescLoop ;loop for next descriptor

;	Done - restore and return.

FHAdjDescDone:

cEnd
	PAGE
;***
; B$FHAdjOneDesc - adjust a far heap descriptor (DOS 3 & 5)
;
;Purpose:
; Added as part of revision [44].
; This routine is called when a single far heap descriptor is about to be
; moved. We traverse the FHD chain in search of the FHD containing a pNext that
; points to the FHD about to move, and then we adjust that pNext to reflect the
; movement. This routine adjusts only one FHD, and stops as soon as a match is
; found, or the end of the FHD chain is found.
;
; NOTE: THIS ROUTINE IS SPEED CRITICAL. The code below is written for speed.
; The main loop deals with TWO successive FHDs each time through the loop to
; eliminate a bit of pointer movement.
;
;Entry:
; [CX]	= adjustment value to the pNext field of the affected far heap
;	  descriptor.
; [DX]	= pointer to FHD which is about to move.
;
;Exit:
; None.
;
;Uses:
; Per Convention
;
;Exceptions:
; None.
;******************************************************************************

cProc	B$FHAdjOneDesc,<NEAR,PUBLIC>,<SI>
cBegin

	MOV	SI,OFFSET DGROUP:b$FHDStart ;Start with beginning of list
ADJONELOOP:

DbAssertRel	SI,NZ,0,FH_TEXT,<FHAdjOneDesc hit end of FarHeap Chain>
	MOV	BX,[SI].FHD_pNext ;[BX] = next descriptor in the list
	CMP	BX,DX		;do we point to the FHD of interest?
	JZ	ADJONESI	;Then adjust the next pointer via BX

DbAssertRel	BX,NZ,0,FH_TEXT,<FHAdjOneDesc hit end of FarHeap Chain>
	MOV	SI,[BX].FHD_pNext ;[SI] = next descriptor in the list
	CMP	SI,DX		;do we point to the FHD of interest?
	JNZ	ADJONELOOP	;Loop until we do or are done

	MOV	SI,BX		;[SI] = pointer to preceding FDH for adjust
ADJONESI:
	ADD	[SI].FHD_pNext,CX ;adjust FH desc list
ADJONEDONE:

cEnd



;***
; B$SETM - SETMEM function runtime entry point (DOS 3 & 5)
;
;Purpose:
;	To attempt to adjust the top limit of the far heap by the
;	(signed) number of bytes in the input parameter.  The function
;	returns the space allocated for both the near and far heaps in bytes.
;Entry:
;	[SP+4] = low-order word of adjustment value.
;	[SP+6] = high-order word of adjustment value.
;Exit:
;	DX:AX = 32-bit size of near and far heaps in bytes.
;Uses:
;	None.
;Exceptions:
;	None.
;******************************************************************************

cProc	B$SETM,<FAR,PUBLIC>
	parmD	incr
cBegin

;	Get adjustment value in DX:AX.

	MOV	AX,off_incr	;get low-order word
	MOV	DX,seg_incr	;get high-order word


;	Test sign of adjustment value and jump if negative.

	OR	DX,DX		;test if adjustment is negative
	JS	FHSetMemNeg	;if so, then jump

;	Positive adjustment.  Get request in AX and raise far heap top.

	CALL	FHSetMemReq	;get request value in AX
	CALL	B$FHRaiseTop	;attempt to raise far heap top
	JMP	SHORT FHSetMemCommon  ;jump to common code to finish

;	Negative adjustment.  Negate value, get request in AX, and lower
;	the far heap

FHSetMemNeg:
	NEG	AX		;negate lower word of value in DX:AX
	ADC	DX,0		;propagate carry to upper word
	NEG	DX		;and negate upper word to finish
FHSetMemLower:			
	CALL	FHSetMemReq	;get request value in AX
	CALL	B$FHLowerTop	;attempt to lower far heap top

;	Common code.  Calculate size of far and near heaps and
;	return value to caller.

FHSetMemCommon:
	CALL	B$FHTestRaiseBottom ; and attempt to raise bottom also
	CALL	FHSetMemValue	;compute size in DX:AX

				; 32K near heap + 128K far heap
	call	fEditorActive	; did we start with /Editor
	jnz	SetMem_Exit	; brif so, allow anything
	cmp	dx,2		; less than 128K total free?
	jb	SetMem_Exit	; brif so -- exit
	ja	TooBig		; brif more than 172K free -- too much free
	or	ax,ax		; less than 128K + 32K free?
	jns	SetMem_Exit	; brif so -- exit

TooBig:				; Reserve <ABOUT> 128K + 32K heap space
	sub	ax,7ff0h	; Can't do 8000h or it will infinite loop!)
	sbb	dx,2		
	jmp	FHSetMemLower	; lower top of far heap by DX:AX
	
SetMem_Exit:			

cEnd

;***
; FHSetMemReq - compute SETMEM request value (DOS 3)
;
;Purpose:
;	Convert the given request value in bytes to paragraphs.
;	If more than 1M bytes, return 0FFFFH paragraphs.
;Entry:
;	DX:AX = 32-bit request value in bytes.
;Exit:
;	AX = 16-bit request value in paragraphs.
;Uses:
;	DX.
;Exceptions:
;	None.
;******************************************************************************

cProc	FHSetMemReq,<NEAR>
cBegin

	CALL	FHByteToPara	;convert DX:AX in bytes to DX:AX in paragraphs
	OR	DX,DX		;test if over 0FFFFH paragraphs
	JZ	FHSetMemReqOK	;if not, then request is okay as is
	MOV	AX,0FFFFH	;set maximum request
FHSetMemReqOK:

cEnd

;***
; FHSetMemValue - compute the SETMEM function value (DOS 3)
;
;Purpose:
;	Compute the size of the near and far heaps in bytes.
;	This is the value returned by the SETMEM function.
;Entry:
;	None.
;Exit:
;	DX:AX = size of heaps in bytes.
;Uses:
;	None.
;Exceptions:
;	None.
;******************************************************************************

cProc	FHSetMemValue,<NEAR>,<CX>
cBegin

;	Compute the paragraph start of the near heap.

	MOV	AX,b$NH_first	;get DGROUP offset of the near heap start
	MOV	CL,4		;byte-to-paragraph factor is 4
	SHR	AX,CL		;get paragraph offser to DGROUP of NH start
	MOV	CX,DS		;get DGROUP paragraph value
	ADD	AX,CX		;add to get paragraph start of near heap

;	Difference from far heap start to near heap start is value
;	to compute.  Convert size from paragraphs to bytes.

	MOV	DX,b$FHDStart.FHD_hData ;get starting (top) paragraph of FH
	SUB	DX,AX		;paragraph size of near and far heaps
	MOV	AX,DX		;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

;***
; FHSetTop - set new top of the far heap. (DOS 3)
;
;Purpose:
;	Set the new top of the far heap by reallocating the DOS
;	memory block containing the program and updating the starting
;	descriptor which defines the top of the far heap.
;Entry:
;	AX = number of paragraphs to adjust the far heap top.
;	     (positive grows, negative shrinks)
;Exit:
;	AX = number of paragraphs actually adjusted.  This number
;	     may be different than the entry value if the heap grows
;	     and insufficient memory is available.
;Uses:
;	ES.
;Exceptions:
;	Fatal error if DOS reallocation fails with legal pool size.
;
;******************************************************************************

cProc	FHSetTop,<NEAR>,<BX>
cBegin

;	Attempt to reallocate the DOS block with the given increment
;	of size.

	MOV	ES,__acmdseg	;get DOS memory block address
	MOV	BX,b$FHDStart.FHD_hData ;get top segment of the far heap
	SUB	BX,__acmdseg	;subtract to get present block size
	ADD	BX,AX		;add increment to get new block size
	MOV	AH,4AH		;get DOS function to reallocate
	CALL	B$FHMemDosCall	;call to perform INT and handle fatal errors
	JNC	FHSetTopDone	;if no error, then jump

;	Reallocation failed with attempted increment.  Try to reallocate
;	with the given maximum size returned in BX.

	MOV	AH,4AH		;try the reallocation again
	CALL	B$FHMemDosCall	;call to perform INT and handle fatal errors
	JC	FHSetTopError	;if reallocation failed, then fatal error

;	Reallocation with new block size in BX succeeded.  Update the
;	far heap descriptor for the top of far heap.

FHSetTopDone:
	ADD	BX,__acmdseg	;add to get new top far heap segment
	MOV	AX,BX		;move top segment...
	SUB	AX,b$FHDStart.FHD_hData ;and subtract to get change in top seg
	MOV	b$FHDStart.FHD_hData,BX ;update new top segment in descriptor

cEnd

FHSetTopError:
	JMP	B$ERR_OM_FH	;give out of memory error


;***
; B$FHMemDosCall - perform memory DOS call (DOS 3)
;
;Purpose:
;	Performs the INT 21H for the DOS allocate, deallocate, and
;	reallocate calls.  Error checking is done here to save space.
;Entry:
;	Setup for the appropriate DOS call, this call replaces the
;	INT 21H instruction.  The DOS calls used are allocate memory
;	(48H), deallocate memory (49H), and reallocate memory (4AH).
;Exit:
;	Post-INT 21H register changes.
;Uses:
;	Post-INT 21H register changes.
;Exceptions:
;	B$ERR_MEM if arena is trashed.
;	B$ERR_FHC if bad memory block address.
;******************************************************************************

cProc	B$FHMemDosCall,<NEAR,PUBLIC>
cBegin

	INT	21H		;perform the DOS call
	JNC	FHMemDosReturn	;if successful, then exit now
	CMP	AX,8		;test if out of memory
	JNE	FHMemDosError	;if not, then jump to trap error
	STC			;set the carry again
FHMemDosReturn:

cEnd

FHMemDosError:
	CMP	AX,7		;test if error was arena destroyed
	JNE	FHMemDosBlock	;if not, then invalid block was used
	JMP	B$ERR_MEM	;jump to fatal error for arena destroyed
FHMemDosBlock:
	JMP	B$ERR_FHC	;jump to fatal error for inconsistenct FH

sEnd	FH_TEXT


	END

⌨️ 快捷键说明

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