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

📄 woapmrm.asm

📁 Dos6.0
💻 ASM
📖 第 1 页 / 共 3 页
字号:
; Given a file handle and a dword worth of block size, this routine swap the ;
; xms block image preceeded by the size into the file.			     ;
;									     ;
; (This code works in real mode only, where the XMS memory is not directly   ;
;  accessible and has to be moved into conventional memory before swapping   ;
;  out. However it has been ensured that the portion of conventional memory  ;
;  not holding the winoldap stub is free at this point).		     ;
;									     ;
; We will read in chunks of extended memory into conventional memory and for ;
; the chunk read in we will write out the non zero blocks using our general  ;
; swap out routine.							     ;
;----------------------------------------------------------------------------;

cProc	RMSwapOutXmsBlock,<NEAR,PUBLIC,PASCAL>

	parmW	FileHandle		;handle of the file
	parmD	BankSize		;size of the bank

	localD	lpXmsInvoke		;xms entry function address
	localV	RMXOHeader,8		;to write out node header
	localV	XmsMoveStruct,16	;the move parameter block.
	localW	SegForXmsXfer		;seg to be used for move

cBegin

	cld				;do not take chances with this

; save  the 'AppUsesXms' variable. This will govern whether we swap out
; actual XMS or not.

	mov	ax,2			;want to write 2 bytes
	xor	cx,cx			;high word of count is 0
	mov	si,DataOFFSET AppUsesXMS;ds:si points to size
	cCall	WriteFile,<FileHandle,ds,si,cx,ax>
	njc	RMSwapOutXmsBlockRet	;cannot proceed with error

; save the length of the block
	
	mov	ax,4			;want to write 4 bytes
	xor	cx,cx			;high word of count is 0
	lea	si,BankSize		;ss:si points to size
	cCall	WriteFile,<FileHandle,ss,si,cx,ax>
	njc	RMSwapOutXmsBlockRet	;cannot proceed with error

; if the block size is 0, we do not have to write it out

	mov	si,seg_BankSize		;load the high word
	or	si,off_BankSize		;is the size 0 ?
	njz 	RMSwapOutXmsBlockRet	;return

; if 'AppUsesXMS' is 0 we do not have to write XMS out.

	cmp	AppUsesXMS,0		;did it use XMS ?
	njz 	RMSwapOutXmsBlockRet	;return

; the following code can destroy the DOS memory arena chain currently
; within the low heap area.  It's not safe to make DOS calls with the arena
; list in an inconstant state, so we zap the low heap arena to indicate it's
; the end of the list.	This was found when running SHARE.EXE under DOS
; 4.0.	When doing a set file attribute Int 21h shortly after this
; routine executes, SHARE would hang trying to walk the arena list.  Another
; routine will restore the Low heap arena in a little while.

	mov	es,LowMemArenaSel
	mov	bptr es:[0],'Z'

; now calculate the amount of bytes of reusable low heap area. We will use the
; area from the start of the StubSeg on.

	mov	ax,_WOARLMSEG		;start of stub seg (swapped out)
	mov	SegForXmsXfer,ax	;will use for XMS transfer
	sub	ax,LowMemSel		;amount of reserved area (CS + DS)
	neg	ax			;want to subtract it from -
	add	ax,LowMemParaSize	;- the total low heap size
	call	GetSizeInBytes		;AX:BX has the size in bytes
	and	bx,0fff0h		;make it para multiple

; (note that we have just made the size of conventional memory that we can
;  use for the move to be a multiple of para size and the amount of xms that
;  we want to swap out is also a multiple of a para size.)

; now initialize the xms move structure.

	smov	es,ss			;will have structure built in stack
	lea	si,XmsMoveStruct	;the move structure
	mov	cx,HighMemXmsHandle	;the source handle
	mov	es:[si+4],cx		;save the source handle
	xor	cx,cx			;source offset will start at zero.
	mov	es:[si+6],cx		;low word of source offset
	mov	es:[si+8],cx		;high word of source offset
	mov	es:[si+10],cx		;destination handle = 0
	mov	es:[si+12],cx		;destination offset = 0
	mov	cx,SegForXmsXfer	;area to transfer bytes into
	mov	es:[si+14],cx		;destination segment
	mov	cx,wptr [lpXmsControl+2]
	mov	seg_lpXmsInvoke,cx	;save loword of xms call function
	mov	cx,wptr [lpXmsControl]
	mov	off_lpXmsInvoke,cx	;save hiword of xms call function
	mov	cx,seg_BankSize		;get the hiword of the block size
	mov	dx,off_BankSize		;get the loword of the block size

; move in as much of the XMS block as possible and write it out into the
; file.

RMSwapOutXmsLoop:

; compare size left to swap out and size of area that can be used for the move
; and decide what part to swap out.

	cmp	ax,cx			;compare high words
	nja	RMSwapOutLast		;last portion to swap out
	jb	RMSwapOutNext		;next part to swap out
	cmp	bx,dx			;compare the low words
	nja	RMSwapOutLast		;last portion to swap out

RMSwapOutNext:

	mov	es:[si],bx		;save low word of move length
	mov	es:[si+2],ax		;save high word of move length
	pushem	ds,ax,bx		;save these registers
	mov	ah,0bh			;function code for move
	smov	ds,ss			;ds:si points to move structure
	call	lpXmsInvoke		;call the function to do the move
	mov	di,ax			;save the return code
	popem	ds,ax,bx		;restore the registers
	or	di,di			;was it successful ?
	njz	RMSwapOutFail		;no, return back

; now write the block out to the disk, after zero compressing it.

	pushem	ax,bx,cx,dx,si		;save the relevant registers
	mov	dx,es:[si]		;low word of size moved
	mov	cx,es:[si+2]		;cx:dx has amount to write
	mov	ax,es:[si+14]		;segment where block was moved
	mov	si,0ffffh		;want to actually swap out
	cCall	SwapOutNonZeroBlocks,<FileHandle,ax,cx,dx,si>
	popem	ax,bx,cx,dx,si		;restore registers
	jc	RmSwapOutXmsBlockRet	;error in write, return back


; also write out a gap node with all 0s

	pushem	ax,bx,cx,dx,si		;save the relevant registers
	push	es
	smov	es,ss			;need to access header structure
	lea	di,RMXOHeader		;es:di points to the node header area
	push	di			;save the offset
	xor	ax,ax			;want to write 0
	mov	cx,4			;size of header	in words
	rep	stosw			;initialize it
	pop	di			;es:di points to the NodeHeader
	mov	cx,8			;8 bytes of header to write
	xor	dx,dx			;hiword of number of bytes to write
	cCall	WriteFile,<FileHandle,es,di,dx,cx>
	pop	es			;restore
	popem	ax,bx,cx,dx,si		;restore registers
	jc	RmSwapOutXmsBlockRet	;error in write, return back

; update variables for next move

	sub	dx,bx			;update amount left to swap out
	sbb	cx,ax			;cx:dx has amount left to move
	mov	di,cx			;check to see whether we are done
	or	di,dx			;no more left ?
	jz	RmSwapOutDone		;yes, we are done.

; update move structure for next portion.

	add	es:[si+6],bx		;update loword of source offset
	adc	es:[si+8],ax		;update hiword of source offset
	jmp	RMSwapOutXmsLoop	;continue till done.

RMSwapOutLast:

	mov	ax,cx			;get amount left into ax:bx
	mov	bx,dx			;ax:bx has size of last portion
	jmp	RMSwapOutNext		;move and write it out

RMSwapOutDone:

; need to write out a dummy header to mark the end of the memory image area

	smov	es,ss			;need to access header structure
	lea	di,RMXOHeader		;es:di points to the node header area
	push	di			;save the offset
	xor	ax,ax			;need to zero it out
	mov	cx,4			;size of header	in words
	rep	stosw			;initialize it
	pop	di			;es:di points to the NodeHeader
	mov	cx,8			;8 bytes of header to write
	xor	dx,dx			;hiword of number of bytes to write
	cCall	WriteFile,<FileHandle,es,di,dx,cx>
	jmp	short RMSwapOutXmsBlockRet

RMSwapOutFail:

	stc				;swap out failed

RMSwapOutXmsBlockRet:

cEnd
;----------------------------------------------------------------------------;
; RMSwapInXmsBlock:						   	     ;
;									     ;
; Given a file handle and dword worth of XMS context size, it reads back the ;
; image into it's correct place.				             ;
;									     ;
; It will read in swap groups from the file over zeroed out memory and do the;
; moves.								     ;
;									     ;
; There is a third parameter to this routine, 'OpCode', which when 0ffh will ;
; actually ZEROINT the XMS allocation instead of trying to read from the     ;
; file (in this case the FileHandle is ignored).			     ;
;----------------------------------------------------------------------------;

cProc	RMSwapInXmsBlock,<NEAR,PUBLIC,PASCAL>

	parmW	FileHandle		;handle of the file
	parmD	BankSize		;size of the context
	parmB	OpCode			;ZEROINT or not

	localD	lpXmsInvoke2		;xms entry function address
	localV	XmsMoveStruct2,16	;the move parameter block.
	localW	SegForXmsXfer2		;seg to be used for move

cBegin

	cld				;do not take chances with this

; if the block size is 0, we do not have to swap it in

	mov	si,seg_BankSize		;load the high word
	or	si,off_BankSize		;is the size 0 ?
	njz 	RMSwapInXmsBlockRet	;return

; now calculate the amount of bytes of reusable low heap area. We will start
; from the beginig of the StubSeg (not swapped in yet)

	mov	ax,_WOARLMSEG		;beginig of stubseg
	mov	SegForXmsXfer2,ax	;will use for XMS transfer
	sub	ax,LowMemSel		;reserved area (CS+DS)
	neg	ax			;want to subtract it from -
	add	ax,LowMemParaSize	;- the total low heap size
	call	GetSizeInBytes		;AX:BX has the size in bytes
	and	bx,0fff0h		;make it para multiple

; (note that we have just made the size of conventional memory that we can
;  use for the move to be a multiple of para size and the amount of xms that
;  we want to swap out is also a multiple of a para size.)

; now initialize the xms move structure.

	smov	es,ss			;will have structure built in stack
	lea	si,XmsMoveStruct2	;the move structure
	mov	cx,HighMemXmsHandle	;the source handle
	mov	es:[si+10],cx		;save the destination handle
	xor	cx,cx			;source offset will start at zero.
	mov	es:[si+12],cx		;low word of destination offset
	mov	es:[si+14],cx		;high word of destination offset
	mov	es:[si+4],cx		;source handle = 0
	mov	es:[si+6],cx		;source offset = 0
	mov	cx,SegForXmsXfer2	;area to transfer bytes into
	mov	es:[si+8],cx		;source segment
	mov	cx,wptr [lpXmsControl+2]
	mov	seg_lpXmsInvoke2,cx	;save loword of xms call function
	mov	cx,wptr [lpXmsControl]
	mov	off_lpXmsInvoke2,cx	;save hiword of xms call function
	mov	cx,seg_BankSize		;get the hiword of the block size
	mov	dx,off_BankSize		;get the loword of the block size

; move in as much of the XMS swapped out block that can be held in memory
; and move it back to its original area

RMSwapInXmsLoop:

; compare size left to swap in and size of area that can be used for the move
; and decide what part to swap in.

	cmp	ax,cx			;compare high words
	ja	RMSwapInLast		;last portion to swap in
	jb	RMSwapInNext		;next part to swap in
	cmp	bx,dx			;compare the low words
	ja	RMSwapInLast		;last portion to swap out

RMSwapInNext:

	mov	es:[si],bx		;save low word of move length
	mov	es:[si+2],ax		;save high word of move length

; if OpCode is ZEROINIT then memory is already zero-ed out, just move it.

	cmp	OpCode,0ffh		;ZEROINIT required ?
	jz	RMXmsInBlockReadIn	;yes, skip reading from file.

; zero out the block first.

	pushem	ax,bx,cx,dx
	mov	ax,_WOARLMSEG		;begining of stub
	sub	ax,LowMemSel		;size of reserved area in paras
	cCall	ZeroOutMemory,<LowMemSel,LowMemParaSize,ax>
	popem	ax,bx,cx,dx		

; read one swap group. 

	save	<ax,bx,cx,dx,si>	;save
	cCall	RestoreSwappedGroups,<FileHandle>
	jc	RMSwapInXmsBlockRet	;error, cannot proceed

RMXmsInBlockReadIn:

; now move it to its original position

	pushem	ds,ax,bx		;save these registers
	mov	ah,0bh			;function code for move
	smov	ds,ss			;ds:si points to move structure
	call	lpXmsInvoke2		;call the function to do the move
	mov	di,ax			;save the return code
	popem	ds,ax,bx		;restore the registers
	or	di,di			;was it successful ?
	jz	RMSwapInFail		;no, return back

; update variables for next move

	sub	dx,bx			;update amount left to swap out
	sbb	cx,ax			;cx:dx has amount left to move
	mov	di,cx			;check to see whether we are done
	or	di,dx			;no more left ?
	jz	RmSwapInDone		;yes, we are done.

; update move structure for next portion.

	add	es:[si+12],bx		;update loword of destination offset
	adc	es:[si+14],ax		;update hiword of destination offset
	jmp	RMSwapInXmsLoop		;continue till done.

⌨️ 快捷键说明

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