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

📄 nhstutil.asm

📁 Microsoft MS-DOS6.0 完整源代码
💻 ASM
📖 第 1 页 / 共 4 页
字号:
;	the current block (pointed by SI).
;	If both are unallocated, then combine and try again.

SS_SCAN_NEXT:
	MOV	CX,[DI] 	;get header of next string entry
	TEST	CL,1		;test if next entry is allocated
	JZ	SS_SCAN_TRY_ALLOC ;if so, then try allocation with current
	INC	CX		;get length of string header and data
	JZ	SS_SCAN_TRY_FINAL ;if string end, then try final allocation
	ADD	AX,CX		;add entry length to current header value
	ADD	DI,CX		;move the next block pointer along
	JMP	SHORT SS_SCAN_NEXT ;and continue the scanning

;	Check entry at SI (with header AX) for sufficient room.
;	If not enough, compute the pointer to the entry after the
;	allocated one that stopped the combining.

SS_SCAN_TRY_ALLOC:
	MOV	[SI],AX 	;update the header in the current entry
	CMP	AX,BX		;compare current header with needed one
	JAE	SS_SCAN_ALC	;if enough room, then finish allocation
	MOV	AX,CX		;move header (descriptor) of allocated entry
	MOV	SI,DI		;skip past allocated entry pointed by DI

;	Compute pointer after the allocated entry at SI whose descriptor
;	is pointed by AX.

SS_SCAN_SKIP:
	MOV	DI,AX		;move descriptor pointer for referencing
	ADD	SI,[DI] 	;add length of string to pointer
	ADD	SI,3		;add 2 for header and 1 for even roundup
	AND	SI,NOT 1	;finish roundup process
	CMP	SI,DX		;test new pointer to scan finish
	JBE	SS_SCAN_START	;if not finished, then try again

;	The scan has failed, set carry and return.
;	Set DX to string space end since last entry was allocated.

SS_SCAN_FAILED:
	MOV	DX,SI		;points to string space end
	STC			;set carry to show failure
	RET			;and return to caller

;	Try a final allocation.  If the allocation fails, then scan fails.

SS_SCAN_TRY_FINAL:
	MOV	[SI],AX 	;update current string entry
	CMP	AX,BX		;compare current header with needed one
	JNAE	SS_SCAN_BYPASS	;if not enough room, bypass long jump
SS_SCAN_ALC:
	MOV	[b$STRING_FREE],SI ;set scanned entry as free string
	JMP	SS_ALC		;if room, jump to finish allocation
SS_SCAN_BYPASS:
	MOV	DX,SI		;point to last unallocated entry
	RET			;return to caller with carry set
PAGE
;***
; B$STCPCT - compact string space
; Purpose:
;	Compacts all allocated strings to the bottom of string space.
;	The string descriptors referenced by the string header are
;	adjusted to reflect their movement.
;	The remaining unallocated space is made into the free string.
;
; Inputs:
;	None.
; Outputs:
;	None.
; Modifies:
;	None.
; Exceptions:
;	B$ERR_SSC - nontrappable error if compaction finds corruption
;		  in string space structure.
;****

B$STCPCT:
	PUSH	AX		;save registers used...
	PUSH	BX
	PUSH	CX
	PUSH	SI
	PUSH	DI
	PUSH	ES		
	PUSH	DS		
	POP	ES		;Set ES = DS

	MOV	SI,[b$STRING_FIRST] ;pointer to string scan

;	Skip over leading allocated entries which can be ignored since
;	they will not be moved.

SS_CPCT_SKIP:
	MOV	BX,[SI] 	;get header of scanned string entry
	TEST	BL,1		;test if entry is allocated
	JNZ	SS_CPCT_FIRST_FREE ;if not allocated, skipping is over

;	Entry is allocated.  First test for backpointer consistency.

	MOV	AX,[BX+2]	;get descriptor pointer to string data
	SUB	AX,2		;adjust to point to string header
	CMP	AX,SI		;test for backpointer consistency
	JNE	SSC_ERR 	; if not, signal string space corruption

;	Compute from descriptor string length the entry length and
;	therefore, the next string entry.  Jump to process this new entry

	ADD	SI,[BX] 	;add string length from descriptor
	ADD	SI,3		;add 2 for header length and 1 for roundup
	AND	SI,NOT 1	;complete roundup to next word
	JMP	SHORT SS_CPCT_SKIP ;and try again for next entry

;	First unallocated string found.  Initialize compacted pointer DI.

SS_CPCT_FIRST_FREE:
	MOV	DI,SI		;SI=scan pointer - DI=compacted pointer

;	Unallocated entry encountered in scan.	First test if string space
;	end (0FFFFH) and if so, jump to finish up.  Otherwise advance the
;	scan pointer SI by the entry size.

SS_CPCT_NEXT_FREE:
	INC	BX		;entry size from header value (hdr+size)
	JZ	SS_CPCT_END	;if it was 0FFFFH, then jump for end
	ADD	SI,BX		;advance scan pointer to next entry

;	Process next entry at scan pointer SI.	If entry unallocated, jump
;	to process it above.

SS_CPCT_NEXT_STRING:
	MOV	BX,[SI] 	;get header of scanned entry
	TEST	BL,1		;test if entry is allocated
	JNZ	SS_CPCT_NEXT_FREE ;if not, then jump to advance scan pointer

;	Entry is allocated.  First test for backpointer consistency.

	MOV	AX,[BX+2]	;get string data offset from descriptor
	SUB	AX,2		;adjust to point to string entry
	CMP	AX,SI		;test for consistency
	JNE	SSC_ERR 	; jump to process corruption error

;	Allocated entry at SI must be moved down to compacted space at DI.
;	First adjust descriptor pointer from SI+2 to DI+2.

	MOV	AX,DI		;get compacted space pointer
	ADD	AX,2		;point to new data portion of moved string
	MOV	[BX+2],AX	;and move it to the descriptor pointer

;	Move the string entry at SI to DI.

	MOV	CX,[BX] 	;get length of string to move
	ADD	CX,3		;add 2 for header and 1 for roundup
	SHR	CX,1		;length of entry in words
	REP	MOVSW		;move the string - SI and DI updated
	JMP	SHORT SS_CPCT_NEXT_STRING ;jump to process next entry

;	String space end encountered.  Put space between pointers SI and
;	DI into one unallocation string entry and make it the free string.

SS_CPCT_END:
	SUB	SI,DI		;get length of new free string entry at DI
	JE	SS_CPCT_NO_FREE ;if no space, then just update [b$STRING_FREE]
	DEC	SI		;new value of header (string data + 1)
	MOV	[DI],SI 	;move in new free string header
SS_CPCT_NO_FREE:
	MOV	[b$STRING_FREE],DI ;update new free string pointer

;	Finished with compaction - restore registers and return.

	POP	ES		
	POP	DI		;restore registers...
	POP	SI
	POP	CX
	POP	BX
	POP	AX
	RET			;return to caller

SSC_ERR:			
	JMP	B$ERR_SSC	;[23]
PAGE
;***
; B$STMOV - move string space
; Purpose:
;	Moves string space to the offset specified in AX.  String space
;	start [b$STRING_FIRST] is now set to AX and the free string entry
;	is adjusted since the string space end at [b$STRING_END] remains
;	as the same value.  The space is returned compacted.
;
; Inputs:
;	SI = offset for new string space start.
; Outputs:
;	CF = 0 - no error
;	     1 - error, not enough memory for move
; Modifies:
;	None.
; Exceptions:
;	B$ERR_SSC - nontrappable error if compaction finds corruption
;		  in string space structure.
;****

B$STMOV:
	PUSH	AX		;save registers...
	PUSH	SI


;	Determine if string space is to be expanded, contracted, or
;	neither.

	MOV	AX,[b$STRING_FIRST] ;get present start of string space
	CMP	SI,AX		;test new start with present start offset
	JE	MOVSTR_COMPACT	;if no difference, then just return
	JB	MOVSTR_DOWN	;if less, then expand space

;	Contract string space by compacting, moving allocated
;	strings up in memory, and adjusting the free string size.

	CALL	B$STCPCT	;compact the string space
	CALL	B$STFromLH	;get any leading heap entries
	CALL	SS_MOV_UP	;move allocated strings up to [SI]
				;this call sets carry if not enough memory
	JMP	SHORT MOVSTR_RETURN ;finished - jump to return

;	Expand string space by prefixing an unallocated string entry
;	located from the new offset to the old and then compacting.

MOVSTR_DOWN:
	SUB	AX,SI		;get size of string entry to create
	DEC	AX		;header is data length plus one
	MOV	[SI],AX 	;place header value in string entry
	MOV	[b$STRING_FIRST],SI ;new value of string space start
	MOV	[b$NH_first],SI ; start of string space is start of dynamic
				 ; space for QB4
MOVSTR_COMPACT:
	CALL	B$STCPCT	;compact strings with new entry
	CALL	B$STFromLH	;get any leading heap entries
	CLC			;clear carry for no error

MOVSTR_RETURN:
	POP	SI		;restore registers...
	POP	AX
	RET			;return...
PAGE
;***
; SS_MOV_UP - move allocated string entries up
; Purpose:
;	Assuming a compacted string space, move all allocated entries
;	starting at offset [SI].  This is done by updating the string
;	descriptor offsets to point to the new entry locations and
;	then moving the allocated strings up as a block.  The new free
;	string is then created as well as the new [b$STRING_FIRST] and
;	[b$STRING_FREE] pointers.
;
; Inputs:
;	AX = offset of present string space start.
;	SI = offset for new string space start.
; Outputs:
;	CF = 0 - no error
;	     1 - error, not enough memory for move
; Modifies:
;	AX, SI.
; Exceptions:
;	None.
;****

SS_MOV_UP:
	PUSH	BX		;save registers...
	PUSH	CX
	PUSH	DI
	PUSH	ES		
	PUSH	DS		
	POP	ES		;Set ES = DS
	XCHG	AX,SI		;AX=new offset - SI=present offset
	SUB	AX,SI		;compute adjustment factor for move up

;	Test if enough room exists to move the strings down in memory.
;	The present free string will be reduced by the adjustment factor,
;	so a negative string length sets carry to denote the error.

	CALL	B$STGETFRESIZ	;get size of free string in BX
	CMP	BX,AX		;compare present free length with adj factor
	JB	SS_MOV_RETURN	;return immediately with carry set

;	Scan through the compacted string space using pointer [SI] and
;	adjust the string descriptor referenced by the backpointer by
;	adding AX to the offset word.

SS_MOV_SCAN_LOOP:
	MOV	BX,[SI] 	;get header of current scanned entry
	TEST	BL,1		;test if entry is allocated
	JNZ	SS_MOV_BLOCK	;if not allocated, then end of scan, jump
	ADD	[BX+2],AX	;adjust the descriptor offset up
	ADD	SI,[BX] 	;add string length to scan pointer
	ADD	SI,3		;add for header and round up to next word...
	AND	SI,NOT 1	;if string length was odd
	JMP	SHORT SS_MOV_SCAN_LOOP ;loop to try for next entry

;	Move all allocated strings together up AX bytes in memory.

SS_MOV_BLOCK:
	MOV	SI,[b$STRING_FREE] ;entry past last allocated one
	MOV	CX,SI		;get offset to compute block length...
	SUB	CX,[b$STRING_FIRST] ;by subtracting start of string space
	SHR	CX,1		;get number of words to move
	SUB	SI,2		;point to highest word to move
	MOV	DI,SI		;compute destination...
	ADD	DI,AX		;by adding amount to move up
	STD			;moving up requires direction flag set
	REP	MOVSW		;perform the move of CX words
	CLD			;restore direction flag

;	Adjust string space pointer and create new free entry.

	ADD	[b$STRING_FIRST],AX ;adjust new start of string space
	ADD	[b$NH_first],AX ; start of string space is start of dynamic
				 ; space for QB4
	MOV	BX,[b$STRING_FREE] ;get original free entry offset
	ADD	BX,AX		;compute new free entry offset
	MOV	[b$STRING_FREE],BX ;put in new free entry offset
	MOV	CX,[b$STRING_END]	;get unchanging end offset of string space
	SUB	CX,BX		;get size of new free entry
	DEC	CX		;header is data length + 1 (entry length - 1)
	MOV	[BX],CX 	;define new free entry by inserting header

SS_MOV_RETURN:
	POP	ES		
	POP	DI		;restore registers...
	POP	CX
	POP	BX
	RET			;return to caller
PAGE
;***
; B$STALCMAXTMP	- allocate maximum-sized temporary string
; B$STALCMAXTMPNC      - Allocate maximum-sized temp string w/o compact
; Purpose:
;	Allocate the maximum-sized string availiable and attach it to a temp
;	descriptor. Backpointer in string space set but data is not moved in.
;
; Inputs:
;	None.
; Outputs:
;	DX = Address of string data area.
;	BX = Address of temp string descriptor
; Modifies:
;	None.
; Exceptions:
;	None.
;****

cProc	B$STALCMAXTMP,<PUBLIC,NEAR>	
cBegin					
	CALL	B$STCPCT	;compact the string space

labelNP	<B$STALCMAXTMPNC>	; Alloc after compaction

	CALL	B$STFromLH	;append any leading local heap entries
	CALL	B$STGETFRESIZ	;get the resulting free string size in BX
	PUSH	[b$STRING_FREE]	; Save ptr to free size
	CALL	B$STALCTMP	;use the size in BX to allocate temp string
	POP	[b$STRING_FREE]	; Get back saved value
				; return to caller (PAINT)
cEnd				; End of B$STALCMAXTMP,B$STALCMAXTMPNC

PAGE
;***
;B$STALCTMP - allocate temporary string
;DBCS-callback
;
;Purpose:
;	Allocate the requested amount of free space and attach it to a temp
;	descriptor. Backpointer in string space set but data is not moved in.
;
;Inputs:
;	BX = Length of string
;
;Outputs:
;	DX = Address of string data area.
;	BX = Address of temp string descriptor
;
;Uses:
;	Per Convention
;
;Preserves:
;	AX, CX
;
;Exceptions:
;	None
;****

B$STALCTMP:
	OR	BX,BX
	JZ	ATSNUL		;Nul strings have special descriptor
	CMP	WORD PTR[TMPHDR],0 ;See if we have any temps left
	JZ	TEMPOV
	PUSH	SI
	PUSH	BX
	CALL	B$STALC	;[C1]Allocate the space

ALCTMP: 			;jumped to from MakeTemp
	MOV	SI,[TMPHDR]	;Get the next temp
	MOV	DX,[SI] 	;Make the one after that
	MOV	[TMPHDR],DX	;   the new "next temp"
	POP	[SI]		;Set length in descriptor
	MOV	[BX-2],SI	;Set backpointer
	MOV	[SI+2],BX	;Set pointer in descriptor
	MOV	DX,b$curlevel	;set program level of allocation
	MOV	[SI+4],DX	;  in descriptor
	MOV	DX,BX		;Put data pointer in DX
	MOV	BX,SI		;Need temp descriptor in BX
	POP	SI
	RET

;	Return pointer to null string.

ATSNUL:
	MOV	DX,OFFSET DGROUP:NULSTR
	MOV	BX,OFFSET DGROUP:b$nuldes 
	RET

TEMPOV:
	JMP	B$ERR_ST	; Clean stack and report string temporary ovfl.
PAGE
;***
;B$STMakeTemp - transfer ownership of a string to a temp. (QBI only).
;
;Purpose:
;	Added with revision [22].
;	Transfers ownership of a string to a temp.  This is used
;	for QBI string functions where the return sd lives on the

⌨️ 快捷键说明

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