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