home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
pascal
/
library
/
dos
/
tegl_ii
/
intro
/
execswap.asm
< prev
next >
Wrap
Assembly Source File
|
1991-04-06
|
21KB
|
436 lines
;EXECSWAP.ASM
; Swap memory and exec another program
; Copyright (c) 1988 TurboPower Software
; May be used freely as long as due credit is given
; See EXECSWAP.PAS for details of version history
; Version 1.1 - 3/15/89
; Version 1.2 - 3/29/89
; Version 1.3 - 5/02/89
;-----------------------------------------------------------------------------
DATA SEGMENT WORD PUBLIC
EXTRN BytesSwapped:DWORD ;Bytes to swap to EMS/disk
EXTRN EmsAllocated:BYTE ;True when EMS allocated for swap
EXTRN FileAllocated:BYTE ;True when file allocated for swap
EXTRN EmsHandle:WORD ;Handle of EMS allocation block
EXTRN FrameSeg:WORD ;Segment of EMS page frame
EXTRN FileHandle:WORD ;Handle of DOS swap file
EXTRN SwapName:BYTE ;ASCIIZ name of swap file
EXTRN PrefixSeg:WORD ;Base segment of program
DATA ENDS
;-----------------------------------------------------------------------------
CODE SEGMENT WORD PUBLIC
ASSUME CS:CODE,DS:DATA
PUBLIC ExecWithSwap,FirstToSave
PUBLIC AllocateSwapFile,DeallocateSwapFile
PUBLIC DefaultDrive,DiskFree
PUBLIC EmsInstalled,EmsPageFrame
PUBLIC AllocateEmsPages,DeallocateEmsHandle
;-----------------------------------------------------------------------------
FileAttr EQU 6 ;Swap file attribute (hidden+system)
EmsPageSize EQU 16384 ;Size of EMS page
FileBlockSize EQU 32768 ;Size of a file block
StkSize EQU 128 ;Bytes in temporary stack
lo EQU (WORD PTR 0) ;Convenient typecasts
hi EQU (WORD PTR 2)
ofst EQU (WORD PTR 0)
segm EQU (WORD PTR 2)
;-----------------------------------------------------------------------------
;Variables in CS
EmsDevice DB 'EMMXXXX0',0 ;Name of EMS device driver
UsedEms DB 0 ;1 if swapping to EMS, 0 if to file
BytesSwappedCS DD 0 ;Bytes to move during a swap
EmsHandleCS DW 0 ;EMS handle
FrameSegCS DW 0 ;Segment of EMS page window
FileHandleCS DW 0 ;DOS file handle
PrefixSegCS DW 0 ;Segment of base of program
Status DW 0 ;ExecSwap status code
LeftToSwap DD 0 ;Bytes left to move
SaveSP DW 0 ;Original stack pointer
SaveSS DW 0 ;Original stack segment
PathPtr DD 0 ;Pointer to program to execute
CmdPtr DD 0 ;Pointer to command line to execute
ParasWeHave DW 0 ;Paragraphs allocated to process
CmdLine DB 128 DUP(0) ;Terminated command line passed to DOS
Path DB 64 DUP(0) ;Terminated path name passed to DOS
FileBlock1 DB 16 DUP(0) ;FCB passed to DOS
FileBlock2 DB 16 DUP(0) ;FCB passed to DOS
EnvironSeg DW 0 ;Segment of environment for child
CmdLinePtr DD 0 ;Pointer to terminated command line
FilePtr1 DD 0 ;Pointer to FCB file
FilePtr2 DD 0 ;Pointer to FCB file
TempStack DB StkSize DUP(0) ;Temporary stack
StackTop LABEL WORD ;Initial top of stack
;-----------------------------------------------------------------------------
;Macros
MovSeg MACRO Dest,Src ;Set one segment register to another
PUSH Src
POP Dest
ENDM
MovMem MACRO Dest,Src ;Move from memory to memory via AX
MOV AX,Src
MOV Dest,AX
ENDM
InitSwapCount MACRO ;Initialize counter for bytes to swap
MovMem LeftToSwap.lo,BytesSwappedCS.lo
MovMem LeftToSwap.hi,BytesSwappedCS.hi
ENDM
SetSwapCount MACRO BlkSize ;Return CX = bytes to move this block
LOCAL FullBlk ;...and reduce total bytes left to move
MOV CX,BlkSize ;Assume we'll write a full block
CMP LeftToSwap.hi,0 ;Is high word still non-zero?
JNZ FullBlk ;Jump if so
CMP LeftToSwap.lo,BlkSize ;Low word still a block or more?
JAE FullBlk ;Jump if so
MOV CX,LeftToSwap.lo ;Otherwise, move what's left
FullBlk:SUB LeftToSwap.lo,CX ;Reduce number left to move
SBB LeftToSwap.hi,0
ENDM
NextBlock MACRO SegReg, BlkSize ;Point SegReg to next block to move
MOV AX,SegReg
ADD AX,BlkSize/16 ;Add paragraphs to next segment
MOV SegReg,AX ;Next block to move
MOV AX,LeftToSwap.lo
OR AX,LeftToSwap.hi ;Bytes left to move?
ENDM
EmsCall MACRO FuncAH ;Call EMM and prepare to check result
MOV AH,FuncAH ;Set up function
INT 67h
OR AH,AH ;Error code in AH
ENDM
DosCallAH MACRO FuncAH ;Call DOS subfunction AH
MOV AH,FuncAH
INT 21h
ENDM
DosCallAX MACRO FuncAX ;Call DOS subfunction AX
MOV AX,FuncAX
INT 21h
ENDM
InitSwapFile MACRO
MOV BX,FileHandleCS ;BX = handle of swap file
XOR CX,CX
XOR DX,DX ;Start of file
DosCallAX 4200h ;DOS file seek
ENDM
HaltWithError MACRO Level ;Halt if non-recoverable error occurs
MOV AL,Level ;Set errorlevel
DosCallAH 4Ch
ENDM
MoveFast MACRO ;Move CX bytes from DS:SI to ES:DI
CLD ;Forward
SHR CX,1 ;Convert to words
REP MOVSW ;Move the words
RCL CX,1 ;Get the odd byte, if any
REP MOVSB ;Move it
ENDM
SetTempStack MACRO ;Switch to temporary stack
MOV AX,OFFSET StackTop ;Point to top of stack
MOV BX,CS ;Temporary stack in this code segment
CLI ;Interrupts off
MOV SS,BX ;Change stack
MOV SP,AX
STI ;Interrupts on
ENDM
;-----------------------------------------------------------------------------
;function ExecWithSwap(Path, CmdLine : string) : Word;
ExecWithSwap PROC FAR
PUSH BP
MOV BP,SP ;Set up stack frame
;Move variables to CS where we can easily access them later
MOV Status,1 ;Assume failure
LES DI,[BP+6] ;ES:DI -> CmdLine
MOV CmdPtr.ofst,DI
MOV CmdPtr.segm,ES ;CmdPtr -> command line string
LES DI,[BP+10] ;ES:DI -> Path
MOV PathPtr.ofst,DI
MOV PathPtr.segm,ES ;PathPtr -> path to execute
MOV SaveSP,SP ;Save stack position
MOV SaveSS,SS
MovMem BytesSwappedCS.lo,BytesSwapped.lo
MovMem BytesSwappedCS.hi,BytesSwapped.hi
MovMem EmsHandleCS,EmsHandle
MovMem FrameSegCS,FrameSeg
MovMem FileHandleCS,FileHandle
MovMem PrefixSegCS,PrefixSeg
InitSwapCount ;Initialize bytes LeftToSwap
;Check for swapping to EMS or file
CMP EmsAllocated,0 ;Check flag for EMS method
JZ NotEms ;Jump if EMS not used
JMP WriteE ;Swap to EMS
NotEms: CMP FileAllocated,0 ;Check flag for swap file method
JNZ WriteF ;Swap to file
JMP ESDone ;Exit if no swapping method set
;Write to swap file
WriteF: MovSeg DS,CS ;DS = CS
InitSwapFile ;Seek to start of swap file
JNC EF0 ;Jump if success
JMP ESDone ;Exit if error
EF0: SetSwapCount FileBlockSize ;CX = bytes to write
MOV DX,OFFSET FirstToSave ;DS:DX -> start of region to save
DosCallAH 40h ;File write
JC EF1 ;Jump if write error
CMP AX,CX ;All bytes written?
JZ EF2 ;Jump if so
EF1: JMP ESDone ;Exit if error
EF2: NextBlock DS,FileBlockSize ;Point DS to next block to write
JNZ EF0 ;Loop if bytes left to write
MOV UsedEms,0 ;Flag we used swap file for swapping
DosCallAH 45h ;DUP handle
JC EF2a ;Jump if failed
MOV BX,AX ;Prepare to close dup'ed handle
DosCallAH 3Eh ;Flush swap file
EF2a: JMP SwapDone ;Done swapping out
;Write to EMS
WriteE: MOV ES,FrameSeg ;ES -> page window
MOV DX,EmsHandle ;DX = handle of our EMS block
EmsCall 47h ;Save EMS context
XOR BX,BX ;BX = initial logical page
MovSeg DS,CS ;DS = CS
EE0: XOR AL,AL ;Physical page 0
EmsCall 44h ;Map physical page
JZ EE1 ;Jump if success
JMP ESDone ;Exit if error
EE1: SetSwapCount EmsPageSize ;CX = Bytes to move
XOR DI,DI ;ES:DI -> base of EMS page
MOV SI,OFFSET FirstToSave ;DS:SI -> region to save
MoveFast ;Move CX bytes from DS:SI to ES:DI
INC BX ;Next logical page
NextBlock DS,EmsPageSize ;Point DS to next page to move
JNZ EE0 ;Loop if bytes left to move
EmsCall 48h ;Restore EMS context
MOV UsedEms,1 ;Flag we used EMS for swapping
;Shrink memory allocated to this process
SwapDone:MOV AX,PrefixSegCS
MOV ES,AX ;ES = segment of our memory block
DEC AX
MOV DS,AX ;DS = segment of memory control block
MOV CX,DS:[0003h] ;CX = current paragraphs owned
MOV ParasWeHave,CX ;Save current paragraphs owned
SetTempStack ;Switch to temporary stack
MOV AX,OFFSET FirstToSave+15
MOV CL,4
SHR AX,CL ;Convert offset to paragraphs
ADD BX,AX
SUB BX,PrefixSegCS ;BX = new paragraphs to keep
DosCallAH 4Ah ;SetBlock
JNC EX0 ;Jump if successful
JMP EX5 ;Swap back and exit
;Set up parameters and call DOS Exec
EX0: MOV AX,ES:[002Ch] ;Get environment segment
MOV EnvironSeg,AX
MovSeg ES,CS ;ES = CS
LDS SI,PathPtr ;DS:SI -> path to execute
MOV DI,OFFSET Path ;ES:DI -> local ASCIIZ copy
CLD
LODSB ;Read current length
CMP AL,63 ;Truncate if exceeds space set aside
JB EX1
MOV AL,63
EX1: MOV CL,AL
XOR CH,CH ;CX = bytes to copy
REP MOVSB
XOR AL,AL
STOSB ;ASCIIZ terminate
LDS SI,CmdPtr ;DS:SI -> Command line to pass
MOV DI,OFFSET CmdLine ;ES:DI -> Local terminated copy
LODSB
CMP AL,126 ;Truncate command if exceeds space
JB EX2
MOV AL,126
EX2: STOSB
MOV CL,AL
XOR CH,CH ;CX = bytes to copy
REP MOVSB
MOV AL,0DH ;Terminate with ^M
STOSB
MovSeg DS,CS ;DS = CS
MOV SI,OFFSET CmdLine
MOV CmdLinePtr.ofst,SI
MOV CmdLinePtr.segm,DS ;Store pointer to command line
INC SI
MOV DI,OFFSET FileBlock1
MOV FilePtr1.ofst,DI
MOV FilePtr1.segm,ES ;Store pointer to filename 1, if any
DosCallAX 2901h ;Parse FCB
MOV DI,OFFSET FileBlock2
MOV FilePtr2.ofst,DI
MOV FilePtr2.segm,ES ;Store pointer to filename 2, if any
DosCallAX 2901h ;Parse FCB
MOV DX,OFFSET Path
MOV BX,OFFSET EnvironSeg
DosCallAX 4B00h ;Exec
JC EX3 ;Jump if error in DOS call
XOR AX,AX ;Return zero for success
EX3: MOV Status,AX ;Save DOS error code
;Set up temporary stack and reallocate original memory block
SetTempStack ;Set up temporary stack
MOV ES,PrefixSegCS
MOV BX,ParasWeHave
DosCallAH 4Ah ;SetBlock
JNC EX4 ;Jump if no error
HaltWithError 0FFh ;Must halt if failure here
EX4: InitSwapCount ;Initialize LeftToSwap
;Check which swap method is in use
EX5: CMP UsedEms,0
JZ ReadF ;Jump to read back from file
JMP ReadE ;Read back from EMS
;Read back from swap file
ReadF: MovSeg DS,CS ;DS = CS
InitSwapFile ;Seek to start of swap file
JNC EF3 ;Jump if we succeeded
HaltWithError 0FEh ;Must halt if failure here
EF3: SetSwapCount FileBlockSize ;CX = bytes to read
MOV DX,OFFSET FirstToSave ;DS:DX -> start of region to restore
DosCallAH 3Fh ;Read file
JNC EF4 ;Jump if no error
HaltWithError 0FEh ;Must halt if failure here
EF4: CMP AX,CX
JZ EF5 ;Jump if full block read
HaltWithError 0FEh ;Must halt if failure here
EF5: NextBlock DS,FileBlockSize ;Point DS to next page to read
JNZ EF3 ;Jump if bytes left to read
JMP ESDone ;We're done
;Copy back from EMS
ReadE: MOV DX,EmsHandleCS ;DX = handle of our EMS block
EmsCall 47h ;Save EMS context for next time
MOV DS,FrameSegCS ;DS -> page window
XOR BX,BX ;BX = initial logical page
MovSeg ES,CS ;ES = CS
EE3: XOR AL,AL ;Physical page 0
EmsCall 44h ;Map physical page
JZ EE4 ;Jump if success
HaltWithError 0FDh ;Must halt if failure here
EE4: SetSwapCount EmsPageSize ;CX = Bytes to move
XOR SI,SI ;DS:SI -> base of EMS page
MOV DI,OFFSET FirstToSave ;ES:DI -> region to restore
MoveFast ;Move CX bytes from DS:SI to ES:DI
INC BX ;Next logical page
NextBlock ES,EmsPageSize ;Point ES to next page to move
JNZ EE3 ;Jump if so
EmsCall 48h ;Restore EMS context
ESDone: CLI ;Switch back to original stack
MOV SS,SaveSS
MOV SP,SaveSP
STI
MOV AX,SEG DATA
MOV DS,AX ;Restore DS
MOV AX,Status ;Return status
POP BP
RET 8 ;Remove parameters and return
ExecWithSwap ENDP
;-----------------------------------------------------------------------------
;Label marks first location to swap
EVEN
FirstToSave:
;-----------------------------------------------------------------------------
;function AllocateSwapFile : Boolean;
AllocateSwapFile PROC NEAR
MOV CX,FileAttr ;Attribute for swap file
MOV DX,OFFSET SwapName+1 ;DS:DX -> ASCIIZ swap name
DosCallAH 3Ch ;Create file
MOV FileHandle,AX ;Save handle assuming success
MOV AL,0 ;Assume failure
JC ASDone ;Failed if carry set
INC AL ;Return true for success
ASDone: RET
AllocateSwapFile ENDP
;-----------------------------------------------------------------------------
;procedure DeallocateSwapFile;
DeallocateSwapFile PROC NEAR
MOV BX,FileHandle ;Handle of swap file
DosCallAH 3Eh ;Close file
XOR CX,CX ;Normal attribute
MOV DX,OFFSET SwapName+1 ;DS:DX -> ASCIIZ swap name
DosCallAX 4301h ;Set file attribute
DosCallAH 41h ;Delete file
RET
DeallocateSwapFile ENDP
;-----------------------------------------------------------------------------
;function EmsInstalled : Boolean;
EmsInstalled PROC FAR
PUSH DS
MovSeg DS,CS ;DS = CS
MOV DX,OFFSET EmsDevice ;DS:DX -> EMS driver name
DosCallAX 3D02h ;Open for read/write
POP DS
MOV BX,AX ;Save handle in case one returned
MOV AL,0 ;Assume FALSE
JC EIDone
DosCallAH 3Eh ;Close file
MOV AL,1 ;Return TRUE
EIDone: RET
EmsInstalled ENDP
;-----------------------------------------------------------------------------
;function EmsPageFrame : Word;
EmsPageFrame PROC FAR
EmsCall 41h ;Get page frame
MOV AX,BX ;AX = segment
JZ EPDone ;Done if Error = 0
XOR AX,AX ;Else segment = 0
EPDone: RET
EmsPageFrame ENDP
;-----------------------------------------------------------------------------
;function AllocateEmsPages(NumPages : Word) : Word;
AllocateEmsPages PROC FAR
MOV BX,SP ;Set up stack frame
MOV BX,SS:[BX+4] ;BX = NumPages
EmsCall 43h ;Allocate EMS
MOV AX,DX ;Assume success
JZ APDone ;Done if not 0
MOV AX,0FFFFh ;$FFFF for failure
APDone: RET 2 ;Remove parameter and return
AllocateEmsPages ENDP
;-----------------------------------------------------------------------------
;procedure DeallocateEmsHandle(Handle : Word);
DeallocateEmsHandle PROC FAR
MOV BX,SP ;Set up stack frame
MOV DX,SS:[BX+4] ;DX = Handle
EmsCall 45h ;Deallocate EMS
RET 2 ;Remove parameter and return
DeallocateEmsHandle ENDP
;-----------------------------------------------------------------------------
;function DefaultDrive : Char;
DefaultDrive PROC FAR
DosCallAH 19h ;Get default drive
ADD AL,'A' ;Convert to character
RET
DefaultDrive ENDP
;-----------------------------------------------------------------------------
;function DiskFree(Drive : Byte) : LongInt;
DiskFree PROC FAR
MOV BX,SP ;Set up stack frame
MOV DL,SS:[BX+4] ;DL = Drive to check
DosCallAH 36h ;Get disk space
MOV DX,AX ;Return 0FFFFFFFFh for failure
CMP AX,0FFFFh ;Bad drive number?
JZ DFDone ;Jump if so
MUL CX ;AX = bytes/cluster
MUL BX ;DX:AX = bytes free
DFDone: RET 2 ;Remove parameter and return
DiskFree ENDP
;-----------------------------------------------------------------------------
CODE ENDS
END