📄 woapmrm.asm
字号:
; 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 + -