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

📄 woautils.asm

📁 Dos6.0
💻 ASM
📖 第 1 页 / 共 3 页
字号:
short_zero_block_size:

	add	di,dx			;update past the short block
	shr	dx,1			;convert to words
	sub	cx,dx			;update count left in segment
	jmp	continue_check_for_zero	;keep looking ahead

scan_block_for_all_0s:

	mov	di,bx			;go back to start of block
	pushem	cx,di			;save
	mov	cx,dx			;block size to look for
	shr	cx,1			;convert size to words.
	repe	scasw			;look for non zero.
	or	cx,cx			;all zeros ?
	popem	cx,di			;retrieve cx
	jnz	short_zero_block_size	;no, zero block not of min size
	add	di,dx			;past the zero block
	jc	go_to_next_seg		;forget about these zeros.
	and	di,0fff0h		;take it back to para start.
	mov	RestartOffset,di	;save next start scan point

; we have got a zero block of atleast the minimum size.

	
	mov	di,bx			;get the start of the block.
	add	di,15			;want to align to the next para
	and	di,0fff0h		;para aligned.
	jmp	ZeroBlockFound		;have got a block of zeros.

go_to_next_seg:

; update size left to be scanned.

	mov	cx,LoopSize		;get the size
	shl	cx,1			;get byte size
	sbb	seg_SLeft,0		;update hiword
	sub	off_SLeft,cx		;subtract from low word
	sbb	seg_SLeft,0		;update hiword

; update the sizes left and the current size.

	mov	cx,LoopSize		;get the size that we inspected
	shl	cx,1			;convert to bytes.
	adc	seg_CSize,0		;add cary to hiword
	add	off_CSize,cx		;add loword
	adc	seg_CSize,0		;add cary to hiword

; update to the next segment.

	mov	bx,ArenaWalkSel		;get the current selector
	call	GetSelectorBase		;get the base
	inc	cx			;next segment
	call	SetSelectorBaseLim64	;update to next seg
	mov	ArenaWalkSel,bx		;save
	jmp	ScanForZerosLoop	;continue.

ZeroBlockFound:

; update the sizes for the current swap group and the amount left to look

	add	off_CSize,di		;include till the zeros
	adc	seg_CSize,0		;update high word

	mov	di,RestartOffset	;we have basically scanned this much
	sub	off_SLeft,di		;amount left
	sbb	seg_SLeft,0

WriteSwapGroup:

	mov	bx,ArenaRWSel		;load the temp selector	for read/write
	mov	cx,seg_CBase		;load hiword of base of block
	mov	dx,off_CBase		;load the loword of the base
	call	SetSelectorBaseLim64	;point the selector to the base
	mov	ArenaRWSel,bx		;save the modified selector

; update the size that is being written.

	mov	dx,seg_CSize		;get the hiword
	mov	ax,off_CSize		;offset
	add	ax,8			;for the node header
	adc	dx,0			;update hiword
	add	off_SONZBSize,ax	;update loword of total size
	adc	seg_SONZBSize,dx	;update hiword.

; if the opcode is for get size only, then bypass the write.

	cmp	SONZBOpCode,0		;get size only ?
	jz	SONZBByPassIO1		;yes.
	
; write the header for the node, which consists of a dword of the value of the
; base of the block followed by a dword of the size of the block

	smov	es,ss			;need to access NHeader in stack
	lea	di,NHeader		;es:di points to the node header
	push	di			;save offset
	mov	ax,off_CBase		;get the low word of base
	stosw				;save it
	mov	ax,seg_CBase		;get the high word of base
	stosw				;save it
	mov	ax,off_CSize		;get the low word of size
	stosw				;save it
	mov	ax,seg_CSize		;get the high word of size
	stosw				;save it
	pop	di			;es:di points to the NHeader
	mov	cx,8			;8 bytes of header to write
	xor	dx,dx			;hiword of number of bytes to write
	cCall	WriteFile,<FHandle,es,di,dx,cx>
	njc	SwapNonZeroBlocksRet	;cannot proceed with error.

; now write out the allocated block contents.

	xor	ax,ax			;need for the start offset
	cCall	WriteFile,<FHandle,ArenaRWSel,ax,CSize>
	njc	SwapNonZeroBlocksRet	;cannot proceed with error.

SONZBByPassIO1:

; if we are done, we should write the end header and leave.

	mov	ax,seg_SLeft		;get the size left 
	or	ax,off_SLeft		;is it 0 ?
	njz	SwapNonZeroBlocksRet	;yes, done with the swap

ScanForNonZerosloop:

; if the RestartOffset is 0, we should go to the next segment.

	cmp	RestartOffset,0		;is it 0
	jnz	restart_in_same_seg	;no, we will restart in same seg.

; update to next segment.

	mov	bx,ArenaWalkSel		;get the current selector
	call	GetSelectorBase		;get the base
	inc	cx			;next segment
	call	SetSelectorBaseLim64	;update to next seg
	mov	ArenaWalkSel,bx		;save

restart_in_same_seg:

	mov	es,ArenaWalkSel		;get the selector into es
	mov	ax,seg_SLeft		;are we all done ?
	or	ax,off_SLeft		
	njz	SwapNonZeroBlocksRet	;yes, done with the swap

; get the min of (seg size in words, amount left in this segment , amount
;  left altogether).

	mov	ax,8000h		;seg size in words
	cmp	seg_SLeft,0		;last segment ?
	jnz	@f			;no.
	push	bx
	mov	ax, off_SLeft
	mov	bx, RestartOffset
	neg	bx
	cmp	ax, bx			;
	jbe	ROWontOverShoot		;S_Left is smaller
	or	bx,bx			;maybe bx is zero
	jz	ROWontOverShoot

; we have to ensure that di which will get the value of RestartOffset
; later, does not cros 0ffffh. If ax > bx this could happen.

	mov	ax,bx			;bx is non zero AND less than ax
ROWontOverShoot:
	pop	bx
	shr	ax,1			;convert to words
	jmp	short start_check_for_non_0	
@@:
	cmp	RestartOffset,0		;is it at start of segment ?
	jz	start_check_for_non_0	;yes
	mov	ax,RestartOffset	;get the start
	neg	ax			;amount left in seg
	shr	ax,1			;convert to words

start_check_for_non_0:

	mov	cx,ax			;get scan size in segment in words

; scan for non zeros in this segment.

	xor	ax,ax			;looking for zeros.
	mov	di,RestartOffset	;start from this point
	repe	scasw			;look for zero.
	or	cx,cx			;0?
	jnz	non_zero_found		;no.

; update size left.
	
	push	di			;save
	sub	di,RestartOffset	;amount scanned 
	sub	off_SLeft,di		;subtract
	sbb	seg_SLeft,0		;hiword.
	pop	di

; if both RestartOffset and current DI are 0 we have skipped a complete 
; segment.

	push	di			;save
	or	di,RestartOffset	;skipped one complete segment ?
	pop	di			;restore di
	mov	RestartOffset,0		;next scan from here.	
	jnz	ScanForNonZerosLoop	;no.
	dec	seg_SLeft		;0=>64k
	jmp	ScanForNonZerosLoop	;continue

non_zero_found:

; this segment has some non zero bytes. Start swapping from the previous 
; paragraph though.

	sub	di,2			;go back to start of non zero stretch
	and	di,0fff0h		;go back to start of para

; update the size left.

	mov	bx,di			;get the current offset
	sub	bx,RestartOffset	;place we started from
	sub	off_SLeft,bx		;account for the skipped part.
	sbb	seg_SLeft,0		;update hiword.
	mov	bx,es			;get the current selector
	call	GetSelectorBase		;get the base
	add	dx,di			;update to the start of non 0 block
	adc	cx,0			;update hiword.

; update vars for the next swap group.

	mov	seg_CSize,0		;initialize current size of swap node
	mov	off_CSize,0		;initialize 32 bits
	mov	seg_CBase,cx		;save high word of current base
	mov	off_CBase,dx		;save low word of current base
	call	SetSelectorBaseLim64	;set selector to point to next base
	mov	ArenaWalkSel,bx		;update
	jmp	ScanForZerosLoop	;continue.

SwapNonZeroBlocksRet:

; if the opcode was for get size only, return with the size in DX:AX

	pushf				;save carry flag state
	cmp	SONZBOpCode,0		;get size on;y ?
	jnz	@f			;no.
	mov	dx,seg_SONZBSize	;get hiword of swap size
	mov	ax,off_SONZBSize	;get low word of swap size
@@:
	popf				;restore state of carry flag

cEnd
;----------------------------------------------------------------------------;
; GetBackAppXmsNeeds:							     ;
;									     ;
; This routine looks at the dos app swap file to locate the size of the XMS  ;
; block that the app needs and saves it in 'XmsBankSize'		     ;
;----------------------------------------------------------------------------;

cProc	GetBackAppXmsNeeds,<NEAR,PUBLIC,PASCAL>

	localD	DwordBuffer		;can read in 4 bytes here
	localW	FileHandle		;save file handle here

cBegin

	cld				;do not take chances with this
	mov	ErrorType,ER_APP_SWAP_IN;in case file can't be found
	mov	si,DataOFFSET DosAppSwapFileName
	cCall	SetNormalAttributes,<ds,si>
	mov	ax,2			;open a normal file
	cCall	OpnFile,<ds,si,ax>	;try to open the file
	njc	ErrorHandler		;cannot	swap in
	mov	FileHandle,ax		;save the handle

; now read in the offset to the start of the xms swap area

	lea	ax,DwordBuffer		;read in offset into ss:ax
	xor	cx,cx			;hiword of count of 4 bytes
	mov	bx,4			;need to read in 4 bytes
	cCall	ReadFile,<FileHandle,ss,ax,cx,bx>
	njc	ErrorHandler		;file too small,error

; now seek to the offset that has just been read in

	xor	ax,ax			;need to seek from the start of the file
	cCall	LseekFile,<FileHandle,DwordBuffer,ax>
	njc	ErrorHandler		;file too small,error

; read in the 4 byte XMS memory size

	lea	di,DwordBuffer		;ss:di points to buffer
	xor	ax,ax			;hiword of count is 0
	mov	bx,4			;need to read 4 bytes (loword of count)
	cCall	ReadFile,<FileHandle,ss,di,ax,bx>
	njc	ErrorHandler		;error in reading in

; save the file size in 'XmsBankSize' global variable.

	mov	ax,seg_DwordBuffer	;get the hiword of size
	mov	wptr [XmsBankSize+2],ax	;save it
	mov	ax,off_DwordBuffer	;get the loword of size
	mov	wptr [XmsBankSize],ax	;save it

; return with the handle of the file

	mov	ax,FileHandle		;handle of dos file

cEnd
;----------------------------------------------------------------------------;
; RestoreXmsAndDosAllocatedBlocks:	  				     ;
;									     ;
; This routine takes a long pointer to a swap file name and read in the dos  ;
; memory allocation image that belongs to the old app. The swap file is      ;
; discussed in the header of the routine above.				     ;
;----------------------------------------------------------------------------;

cProc	RestoreXmsAndDosAllocatedBlocks,<NEAR,PUBLIC,PASCAL>

	parmD	lpFileName		;the name of the swap file

	localW	FileHandle		;handle of the swap file
	localD	FileOffset		;place to read in 4 byte offset
	localV	NodeHeader,8		;will read in the node header here

cBegin

	cld				;do not take chances with this

; try to open the swap file. Set normal attributes for the file.

	cCall	SetNormalAttributes,<lpFileName>
	mov	ax,2			;want to open a read only file
	cCall	OpnFile,<lpFileName,ax>	;try to open the file
	jc	RestoreDosAllocatedBlocksRet;cannot proceed with error.
	mov	FileHandle,ax		;save the handle of the swap file

; we first need to restore the XMS context first, so get the offset of the
; start of the XMS area (saved as the first 4 bytes of the file).

	lea	ax,FileOffset		;read in offset into ss:ax
	xor	cx,cx			;hiword of count of 4 bytes
	mov	bx,4			;need to read in 4 bytes
	cCall	ReadFile,<FileHandle,ss,ax,cx,bx>
	jc	RestoreDosAllocatedBlocksRet	

; now seek to the offset that has just been read in

	xor	ax,ax			;need to seek from the start of the file
	cCall	LseekFile,<FileHandle,FileOffset,ax>

; now read in the XMS context. if the app needs XMS memory,we must swap out the 
; block into the XMS file before loading applications XMS blocks

	cCall	RestoreAppXmsContext,<FileHandle>;restore the XMS context
	jc	RestoreDosAllocatedBlocksRet;cannot proceed with error.

; now seek back to the start of the file past the 4 byte offset area for reading
; in the image of the dos app.

	xor	ax,ax			;need zeros for hiword of offset/org.

ifdef	JAPAN
	mov	cx,8			;offset for seek
else
	mov	cx,4			;offset for seek
endif

	cCall	LseekFile,<FileHandle,ax,cx,ax>

; zero out the area where we will read apps context in.	We must zero out 
; from the start of the StubSeg onwards.


	mov	ax,_WOARLMSEG		;start of stub segment
	sub	ax,LowMemSel		;paragraphs at the begining
	cCall	ZeroOutMemory,<LowMemSel,LowMemParaSize,ax>

; now read in the first allocated block. In protected mode the complete block
; had been saved and the size of the block can be obtained after reading in
; the arena. In real mode, the portion of memory right after the arena which
; holds the top pdb and main code and data segments had not been saved and 
; should be skipped during the swap back

  	cCall	RestoreFirstDosBlock,<FileHandle>
	jc	RestoreDosAllocatedBlocksRet;cannot proceed with error.

; now get into a loop reading in header for every node and reading the 
; associated memory image into the right space, till we get a node header
; with a base of zero.

	cCall	RestoreSwappedGroups,<FileHandle>
	mov	ax,FileHandle		;must return with file handle

RestoreDosAllocatedBlocksRet:

cEnd
;----------------------------------------------------------------------------;
; RestoreSwappedGroups:							     ;
;									     ;
; Takes a handle for a swap file as a parameter and reads back swapped out   ;
; groups from the file. The structure of each swap group is a dword of the   ;
; base of the memory where the block is to be read back, a dword of size of  ;
; the block to read in, followed by the image of the block itself. The swap  ;
; groups are terminated by a node header where the base is 0.		     ;
;----------------------------------------------------------------------------;

cProc	RestoreSwappedGroups,<NEAR,PUBLIC,PASCAL>

	parmW	FileHandle		;handle of the swap file

	localV	NodeHeader,8		;will read in the node header here

cBegin

	cld				;do not take chances with this

ReadBlockLoop:

; read in the next node header.

	smov	es,ss			;fill read the header into the stack
	lea	di,NodeHeader		;es:di points to read buffer
	mov	cx,8			;need to read 8 bytes in

⌨️ 快捷键说明

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