📄 woautils.asm
字号:
;/*
; * Microsoft Confidential
; * Copyright (C) Microsoft Corporation 1985-1991
; * All Rights Reserved.
; */
;----------------------------------------------------------------------------;
; This file has utility programs which are invoked mostly from WOAMGR.ASM ;
; ;
; History: ;
; ;
; Fri June-15-1990. -by- Amit Chatterjee [amitc] ;
; Adapted for the Dos Task Switcher. ;
; ;
; Mon June-26-1989. -by- Amit Chatterjee [amitc] ;
; Created for Windows. (Added the History legend) ;
;----------------------------------------------------------------------------;
?win = 0
?DF = 1
.xlist
include cmacros.inc
include woasegs.inc
include macros.mac
include njmp.mac
include dosx.inc
include woapif.inc
include woaerr.inc
include woaarena.inc
include woaswch.inc
.list
.286p
public SaveWinEmsContext
public RestoreWinEmsContext
public GetSizeInBytes
public ConvKToBytes
;----------------------------------------------------------------------------;
; define external FAR winoldap procedures. ;
;----------------------------------------------------------------------------;
sBegin Data
;----------------------------------------------------------------------------;
; define the global variables defined elsewhere ;
;----------------------------------------------------------------------------;
externW ArenaWalkSel ;temp selector for walkimg arena chain
externW ArenaRWSel ;temp sel for reading/writing arenas
externW XmsHeapWalkSel ;scratch selector for walking xms heap
externW WoaStubSel ;sel for current loaction of stub code
externB EmsFlag ;EMS present or not.
externB fBreak ;state of CTRL+C flag.
externW HighMemXmsHandle ;handle of the high heap XMS block
externB DosAppSwapFileName ;name of the dos app swap file
externB ErrorType ;save area for error code
externW WoaCsSize ;size of protected mode code seg
externW WoaDsSize ;size of winoldap data segment
externW StubSegSize ;size of real mode stub segment
externB DiskSwap1Drive ;swap drive index for fast path
externB DiskSwap2Drive ;swap drive index for slow path
externW Swap1MinK ;space to be left on 1st drive
externW Swap2MinK ;space to be left on second drive
externW Int15UsershApp ;hApp of INT 15 user
externW hApp ;windows handle for this instance
externD XmsBankSize ;size of apps XMS bank
externW LowMemParaSize ;para size of available memory
externW LowMemArenaSel ;pointer to the available memory arena
externW LowMemSel ;sel for the start of the vail block
externW SizeReservedArea ;size of area reserved area at heap st.
externW CurrentDosSwapSeed ;swap file seed being used now
externW AppUsesXMS ;app used it's allocated XMS or not
ifdef JAPAN
externD KkcDataSize ; Data area size of KKC
endif
;-------------------------------------------------------;
; define any locally used constants ;
;-------------------------------------------------------;
;-------------------------------------------------------;
; define any locally used constants ;
;-------------------------------------------------------;
ZERO_BLOCK_SIZE equ 128
;-------------------------------------------------------;
; define any external contants. ;
;-------------------------------------------------------;
externB WoaAppSwapErr ;(WOAERR.ASM)
externA IS_WINOLDAP_ACTIVE ;(WOAMGR.ASM)
;---------------------------------------------------------------------------;
; now define the other global variables that will be needed. ;
;---------------------------------------------------------------------------;
;---------------------------------------------------------------------------;
; now define the other variables that will be needed. ;
;---------------------------------------------------------------------------;
WinEmsSaveArea db 256 dup (0) ;save windows EMS context here
globalW AppXmsBaseSel,0 ;selector to base of apps XMS block
;-------------------------------------------;
; Debug messages used if DEBUGMODE is set. ;
;-------------------------------------------;
ifdef DEBUGMODE
endif ;DEBUGMODE
sEnd Data
;----------------------------------------------------------------------------;
; now declare the existence of the realmode stub segment and the variables ;
; that we want to reference here. ;
;----------------------------------------------------------------------------;
createSeg _WOARLMSEG,StubSeg,word,public,code
sBegin StubSeg
sEnd StubSeg
;----------------------------------------------------------------------------;
; we define the switch_cs macro here. ;
;----------------------------------------------------------------------------;
switch_cs macro
local _x
local _y
_x proc far
lea ax,_y
push ax
ret
_y:
_x endp
endm
;----------------------------------------------------------------------------;
sBegin Code
assumes cs,Code
assumes ds,Data
assumes es,nothing
;-------------------------------------------------------;
; external OLDAPP procedures. ;
;-------------------------------------------------------;
externNP DeleteFile ;(WOAFILE.ASM)
externNP ErrorManager ;(WOAERR.ASM)
externNP CreateFile ;(WOAFILE.ASM)
externNP LseekFile ;(WOAFILE.ASM)
externNP OpnFile ;(WOAFILE.ASM)
externNP ReadFile ;(WOAFILE.ASM)
externNP WriteFile ;(WOAFILE.ASM)
externNP CloseFile ;(WOAFILE.ASM)
externNP DeleteFile ;(WOAFILE.ASM)
externNP SetNormalAttributes ;(WOAFILE.ASM)
externNP SetHiddenAttributes ;(WOAFILE.ASM)
externNP GetSelectorBase ;(WOAPMRM.ASM)
externNP SetSelectorBaseLim64 ;(WOAPMRM.ASM)
externNP GetDosAppSwap1FileName ;(WOAMGR.ASM)
externNP GetDosAppSwap2FileName ;(WOAMGR.ASM)
externNP SaveFirstDosBlock ;(WOAPMRM.ASM)
externNP RestoreFirstDosBlock ;(WOAPMRM.ASM)
externNP RestoreAppXmsContext ;(WOAPMRM.ASM)
externNP AppendUniqueNumber ;(WOAMGR.ASM)
externNP ZeroOutMemory ;(WOAPMRM.ASM)
externNP GetSwitcherEntry ;(WOAPMRM.ASM)
;----------------------------------------------------------------------------;
; SaveDosMemory: ;
; ;
; This routine takes the name of the dos swap file as the input. It writes ;
; the first DOS block (or a part of it in real mode) to the swap file and ;
; then traverses memory looking for non zero values and then swaps them ;
; out in groups. ;
; ;
; This routine also takes an OpCode, SDMOpCode which if 0 returns just the ;
; size needed to save the memory and if non zero actually saves the memory. ;
; If the OpCode is 0, the first parameter is insignificant. ;
;----------------------------------------------------------------------------;
cProc SaveDosMemory,<NEAR,PUBLIC,PASCAL>
parmD lpFileName ;name of the swap file
parmB SDMOpCode ;save or get size
localW FileHandle ;handle of the swap file
localV NodeHeader,8 ;DWORDs of base and lock size
localD CurrentSize ;size of the node being prepared
localD CurrentBase ;base of the node being prepared
localD SizeLeft ;amount of memory left
localD SDMSize ;size of save area
cBegin
cld ;do not take chances with this
; Initialize the SDMSize field
mov seg_SDMSize,0
mov off_SDMSize,4 ;4 bytes for XMS link
; create the swap file, at this point the file should not be existing, but
; we do not care to check. Ifthe OpCode is for get size only, we will not
; try to create any file.
cmp SDMOpCode,0 ;get size only
jz SDMByPassIO1 ;yes
xor ax,ax ;want to create a normal file
cCall CreateFile,<lpFileName,ax>
jc SaveDosMemoryRet ;cannot proceed with error.
mov FileHandle,ax ;save the handle of the swap file
; we need to leave 4 bytes at the start of the file for storing the offset
; of the start of the XMS swap out area. This is actually needed only in
; real mode winoldap where the XMS memory has to be swapped in first.
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>
SDMByPassIO1:
; we will save the first block arena selector separately and then skip over
; the _DATA and _TEXT segments. The following routine will do that, it will
; return the size of the block skipped over (top PDB, _DATA & _TEXT) in AX
; and the size wriiten to file (actuall 16) in CX:DX.
cCall SaveFirstDosBlock,<FileHandle,SDMOpCode>;saves the block containing woa stub
jc SaveDosMemoryRet ;cannot proceed with error.
; AX has the para size of the first block. CX:DX has the size wriiten out.
; Calculate the amount of memory left to be swapped.
add off_SDMSize,dx ;add in size wriitent out
adc seg_SDMSize,cx ;update hiword
sub ax,LowMemParaSize ;get difference
neg ax ;convert to positive
call GetSizeInBytes ;AX:BX has the size
mov seg_SizeLeft,ax ;save hiword
mov off_SizeLeft,bx ;save loword
; SetArenaWalkSel to the start of the block from where we want to swap on
; (_WOARLMSEG)
mov ax,_WOARLMSEG ;want to swap from here
mov ArenaWalkSel,ax ;save it
; call the generalized routine to swap out the non zero blocks
cCall SwapOutNonZeroBlocks,<FileHandle,ArenaWalkSel,SizeLeft,SDMOpCode>
jc SaveDosMemoryRet ;cannot proceed with error.
; update the size and add 8 for the following node too. The above routine
; would have returned the size written out in DX:AX
add ax,8 ;for the terminating header
adc dx,0 ;update hiword
add off_SDMSize,ax ;update total size
adc seg_SDMSize,dx ;update hiword
cmp SDMOpCode,0 ;get size only ?
jz SaveDosMemoryRet ;yes.
; 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,NodeHeader ;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>
SaveDosMemoryRet:
mov ax,FileHandle ;need to return the handle of the file
; if the SDMOpCode is zero, return with the size in DX:AX.
pushf ;save state of carry flag
cmp SDMOpCode,0 ;get size only ?
jnz @f ;no.
mov dx,seg_SDMSize ;get hiword of size
mov ax,off_SDMSize ;get low eord of size
@@:
popf ;restore carry flag (success or failure code)
cEnd
;----------------------------------------------------------------------------;
; SwapOutNonZeroBlocks: ;
; ;
; This routine takes the following parameters: ;
; ;
; FileHandle --- Data will be written into this file ;
; Start sel --- Swap out area starts here (offset 0) ;
; Size --- Total size of the area in bytes (dword) ;
; SONZBOpCode --- If 0 will just get the swap area size.
; ;
; It scans the range specified for non zero blocks of zeros and writes out ;
; swap groups (block preeceded by 8 byte header) to the file. It returns ;
; with carry set if the writes failed. ;
;----------------------------------------------------------------------------;
cProc SwapOutNonZeroBlocks,<NEAR,PUBLIC,PASCAL>,<es>
parmW FHandle ;handle for the file
parmW StartSel ;start selector
parmD SLeft ;size for the block
parmB SONZBOpCode ;get size only or not.
localV NHeader,8 ;DWORDs of base and lock size
localD CSize ;current swap group size
localD CBase ;current swap group base
localW LoopSize ;size being tested in the loop
localW RestartOffset ;restart point
localD SONZBSize ;size of the swap area.
cBegin
; initialize the swap area size variable.
mov seg_SONZBSize,0
mov off_SONZBSize,0
; initialize the base and size for the next swap group
mov bx,StartSel ;get the selector
mov ArenaWalkSel,bx ;save it
call GetSelectorBase ;get the base in cx:dx
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
ScanForZerosLoop:
mov es,ArenaWalkSel ;get the selector into es
mov ax,seg_SLeft ;are we all done ?
or ax,off_SLeft
njz WriteSwapGroup ;write the group and end
; need to scan the segment for zeros.
mov cx,8000h ;assume complete segment (in words)
cmp seg_SLeft,0 ;are we in the last 64k seg ?
jnz start_check_for_0 ;no.
mov cx,off_SLeft ;get the size left to look.
shr cx,1 ;convert to words
start_check_for_0:
mov LoopSize,cx ;save the size in words that we test
; scan for zeros in this segment.
xor ax,ax ;looking for zeros.
xor di,di ;start at top of segment.
continue_check_for_zero:
repne scasw ;look for zero.
jcxz go_to_next_seg ;no zeros found.
; the zero stretch should atleast be ZERO_STRETCH_SIZE long.
inc cx ;ignore the match.
sub di,2 ;start of the zeros.
mov bx,di ;save
; look ahead ZERO_STRTECH_SIZE or to the end of segment which ever is smaller
pushem ax,bx
mov ax,cx ;words left in the segment
shl ax,1 ;convert to bytes
mov bx,ZERO_BLOCK_SIZE ;min zero block size
jc enough_in_segment ;complete segment is left
cmp ax,bx ;which is smaller ?
jbe look_ahead_size_obt ;ax has look ahead size
enough_in_segment:
mov ax,bx ;bx is min
look_ahead_size_obt:
mov dx,ax ;have it in dx
popem ax,bx
; from di onwards we want to have a block of DX size as 0s
add di,dx ;look ahead
jc scan_block_for_all_0s ;goes into next seg, see if its all 0
cmp byte ptr es:[di],0 ;is it still 0 ?
jz scan_block_for_all_0s ;possibly 0 stretch obtained.
sub di,dx ;take it back to start of block
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -