home *** CD-ROM | disk | FTP | other *** search
- ;*******************************************************
- ; CHAIN.ASM 5.00
- ; Copyright (c) TurboPower Software 1987.
- ; All rights reserved.
- ;*******************************************************
-
- ;Set the following define to 1 and reassemble CHAIN
- ;if you need to run under DOS 2.X
- DOS2X = 0
-
- DSEG SEGMENT WORD PUBLIC
-
- EXTRN CloseFilesBeforeChaining:BYTE ;Variable in CHAIN.PAS
- EXTRN PrefixSeg:WORD ;Variable in SYSTEM
-
- DSEG ENDS
-
- CSEG SEGMENT BYTE PUBLIC
-
- ASSUME CS:CSEG,DS:DSEG
-
- PUBLIC Chain4
- PUBLIC SetIntVec
- EXTRN RestoreVectors:NEAR ;Routine to restore vectors
-
- ;The following values must be exact
- ;They'll need changing if anything after label CodeToRelocate changes
- CodeLen EQU 02Ch ;Bytes of code to relocate
- MaxCmdLen EQU 052h ;Maximum length of command line
-
- ;Although more reliable, the following generates several NOPs in object code
- ;CodeLen = offset Dummy-offset CodeToRelocate ;Length of code in PSP
- ;MaxCmdLen = 07Eh-CodeLen ;Maximum length of command line
-
- FirstHandle EQU 5 ;First file handle to close
-
- ;**************************************************************** SetIntVec
- ; procedure SetIntVec(Num : Byte; Vec : pointer);
- ; set interrupt Num to point to Vec
-
- SetIntVec PROC NEAR
- MOV BX,SP ;Stack frame
- MOV CX,DS ;Save DS
- MOV AH,25h ;Set vector
- MOV AL,SS:[BX+6] ;AL = Num
- LDS DX,SS:[BX+2] ;DS:DX = Vec
- INT 21h
- MOV DS,CX ;Restore DS
- RET 6
- SetIntVec ENDP
-
- ;**************************************************************** Chain4
- ; function Chain4(Path, CmdLine : string) : word;
- ; Turbo 4 equivalent of chaining
-
- ;Parameters
- PathArg EQU DWORD PTR [BP+10] ;File to chain to
- CmdLine EQU DWORD PTR [BP+6] ;Command line to pass
-
- ;Local variables
- CsInit EQU WORD PTR [BP-30+16h] ;Fields within EXE header
- IpInit EQU WORD PTR [BP-30+14h] ; ...
- StackPtr EQU WORD PTR [BP-30+10h]
- StackSeg EQU WORD PTR [BP-30+0Eh]
- MinHeap EQU WORD PTR [BP-30+0Ah]
- EXEPages EQU WORD PTR [BP-30+04h]
- EXEHeader EQU WORD PTR [BP-30] ;EXE header from file
- Path EQU BYTE PTR [BP-94] ;ASCIIZ path string
-
- Chain4 PROC FAR
-
- PUSH BP
- MOV BP,SP ;Set up stack frame
- SUB SP,94 ;Make space for locals
-
- ;Validate pathname and convert to ASCIIZ
- PUSH DS ;Save DS for later
- PUSH SS
- POP ES ;ES = SS
- LEA DI,Path ;ES:DI => ASCIIZ path
- MOV BX,DI ;Save offset of ASCIIZ
- LDS SI,PathArg ;DS:SI => file path in Turbo string
- ASSUME DS:nothing
- CLD ;Forward
- LODSB ;Get length byte
- CMP AL,63 ;Longer than 63 characters?
- JB StoreASCIIZ
- MOV AL,63 ;Truncate it
- StoreASCIIZ:
- MOV CL,AL ;CX = length
- XOR CH,CH
- REP MOVSB ;Copy to local Path
- XOR AL,AL ;Make ASCIIZ
- STOSB
-
- ;Assure file exists
- PUSH SS
- POP DS ;DS = SS
- MOV DX,BX ;DS:DX => ASCIIZ path
- MOV AX,3D00h ;Open file read-only
- INT 21h
- JNC FileFound ;OK, file was found
-
- Error: POP DS ;Restore DS
- ASSUME DS:DSEG
- Error1: MOV SP,BP ;Return with error code in AX
- POP BP ;Restore BP
- RET 8 ;Remove parameters from stack
-
- ;Read file header
- FileFound:
- MOV BX,AX ;BX = file handle
- LEA DX,ExeHeader ;DS:DX => ExeHeader
- MOV CX,28 ;Read 28 bytes
- MOV AH,3Fh ;DOS read file
- INT 21h
- JC Error ;Error if carry set
- CMP AX,2 ;At least 2 bytes read?
- MOV AX,30 ;Prepare for Read Fault error
- JB Error ;Error if 2 bytes not read
-
- ;Determine how much memory program needs
- CMP ExeHeader,5A4Dh ;Is it EXE format?
- JE ExeFileSize ;Yes, treat it as such
-
- ;Get non-EXE file size
- MOV AX,4202h ;Seek to end of file
- XOR CX,CX
- XOR DX,DX
- INT 21h
- JC Error ;Error if carry set
- MOV CX,4 ;Divide bytes by 16
- NextShiftR:
- SHR DX,1 ;Shift a LongInt right
- RCR AX,1
- LOOP NextShiftR
- JMP SHORT CloseFile ;DX:AX has paragraphs needed
-
- ;Get EXE image size
- ExeFileSize:
- MOV AX,EXEPages ;Get pages in EXE image
- XOR DX,DX
- MOV CX,5 ;Multiply by 32
- NextShiftL:
- SHL AX,1 ;Shift a LongInt left
- RCL DX,1
- LOOP NextShiftL ;DX:AX has paragraphs
- ADD AX,MinHeap ;Add minimum data/stack/heap
- ADC DX,0
-
- ;Close file (DOS will reopen it)
- CloseFile:
- MOV CX,AX ;Save paragraphs in CX
- MOV AH,3Eh ;Close file
- INT 21h
- JC Error ;Error if carry set
-
- ;See if more than 640K bytes requested
- MOV AX,8 ;Prepare for insufficient memory
- OR DX,DX ;DX must be zero
- JNZ Error ;Error if more than 640K
-
- ;Determine available memory space
- POP DS ;Restore DS
- ASSUME DS:DSEG
- MOV ES,PrefixSeg ;Main program segment
- MOV AH,4Ah ;Setblock
-
- IF DOS2X ;Runs under DOS 2.X or 3
- MOV BX,CX
- ADD BX,1000h
- INT 21h ;BX = Required space+64K bytes
-
- ELSE ;Runs only under DOS 3 or later
- MOV BX,0FFFFh ;Ask for everything
- INT 21h ;BX has available paragraphs
- ;Assure sufficient memory available for overlay
- MOV AX,BX
- SUB AX,10h ;Leave space for PSP
- CMP AX,CX ;Sufficient space?
- MOV AX,8 ;Prepare for insufficient memory
- JB Error1 ;Error if less
- ENDIF
-
- ;Allocate all available space
- MOV AH,4Ah ;Ask again for what we can get
- INT 21h
- JC Error1 ;Error if carry set now
-
- ;Prepare to move stack to top of memory
- MOV AX,ES ;Base of program
- ADD AX,BX ;Add all available paragraphs
- SUB AX,1000h ;Room for full stack segment
- MOV CS:TmpSS,AX ;Store temporary SS for later
-
- ;Close secondary file handles (don't touch StdIn,StdOut,StdErr,StdPrn)
- CMP CloseFilesBeforeChaining,0 ;Should we close files?
- JZ RestoreInts ;No, skip this
- MOV BX,FirstHandle ;Start with handle 5
- MOV CX,20-FirstHandle ;20 handles total
- NextHandle:
- MOV AH,3Eh ;DOS close file
- INT 21h
- INC BX ;Ignore errors
- LOOP NextHandle
-
- ;Restore interrupt vectors taken over by SYSTEM library
- RestoreInts:
- PUSH ES
- CALL RestoreVectors
- POP ES
-
- ;Set up command line for chained program
- LDS SI,CmdLine ;DS:SI points to command line
- MOV DI,80h ;ES:DI => command line in PSP
- LODSB ;Get length byte
- CMP AL,MaxCmdLen ;Is is too long?
- JB StoreCmdLine ;No, don't truncate
- MOV AL,MaxCmdLen ;Truncate
- StoreCmdLine:
- STOSB ;Store length byte
- MOV BX,DI ;Save start of command line
- MOV CL,AL
- XOR CH,CH
- REP MOVSB ;Copy parameter to command line
- MOV AL,0Dh ;Terminate with <Enter>
- STOSB
-
- ;Initialize FCB's for new program
- PUSH ES
- POP DS ;DS = ES
- MOV SI,BX ;DS:SI => command line to parse
- MOV DI,005Ch ;ES:DI => FCB1
- MOV AX,2901h ;Init FCB1
- INT 21h
- MOV DI,006Ch ;ES:DI => FCB2
- MOV AX,2901h ;Init FCB2
- INT 21h
-
- ;Save initialization data for new program
- MOV BX,ES ;Store prefix seg in BX
- MOV CS:NewCS,BX ;Assume COM file
- MOV CS:NewSS,BX
- ADD BX,10h ;BX = base segment of image
- CMP ExeHeader,5A4Dh ;Is it EXE format?
- JNE MoveCode ;No, COM file already initialized
- MOV AX,CsInit ;Get initial CS from EXE header,
- ADD AX,BX ; relocate segment,
- MOV CS:NewCS,AX ; save it for later
- MOV AX,IpInit ;Initial IP
- MOV CS:NewIP,AX
- MOV AX,StackSeg ;Initial SS
- ADD AX,BX
- MOV CS:NewSS,AX
- MOV AX,StackPtr ;Initial SP
- MOV CS:NewSP,AX
-
- ;Move code into PSP
- MoveCode:
- MOV CX,CodeLen ;Bytes to move
- MOV DI,100h ;DI => end of new code
- SUB DI,CX ;ES:DI => destination of new code
- MOV CS:TmpIP,DI ;Store address to jump to
- MOV CS:TmpCS,ES
- PUSH CS
- POP DS ;DS = CS
- MOV SI,offset CodeToRelocate ;DS:SI => code to relocate
- REP MOVSB ;Copy the code to PSP
-
- ;Prepare for EXEC call
- MOV AX,BX ;AX = Base segment
- STOSW
- STOSW ;Initialize EXEC block
- PUSH SS
- POP DS ;DS = SS
- LEA DX,Path ;DS:DX => Path of file
- MOV BX,100h ;ES:BX => EXEC block
- MOV AX,4B03H ;Load Overlay
- CLI
- MOV SS,CS:TmpSS ;Put stack at top
- MOV SP,0FFFEh ; of memory
- STI
- DB 0EAh ;JMP FAR to code in PSP
- TmpIP DW 0 ;Patched in with offset
- TmpCS DW 0 ;Patched in with segment
- TmpSS DW 0 ;Temporary stack segment
-
- ;-----------------------------------------------------------------------------
- ;Code relocated to and executed in PSP
- CodeToRelocate:
- INT 21h ;Call DOS EXEC
- JNC GoodLoad ;Check for error
- INT 20h ;Error is rare
- ; just halt if EXEC failed
- GoodLoad:
- MOV DX,CS ;Get base of program
- MOV DS,DX ;Initialize DS
- MOV ES,DX ;Initialize ES
- MOV AH,4Ah ;DOS SetBlock
- MOV BX,0FFFFh ;Ask for everything
- INT 21h ;BX has available paragraphs
- ADD BX,DX ;Top of memory
- MOV DS:[0002h],BX ;Store in PSP that Turbo uses
- CLI ;Interrupts off
- MOV SS,DS:[0FEh] ;Initialize stack
- MOV SP,DS:[0FCh]
- STI ;Interrupts on again
- DB 0EAh ;JMP FAR to start of code
- NewIP DW 100h ;Patched in with start offset
- NewCS DW 0 ;Patched in with start segment
- NewSP DW 0FFFEh ;Patched in with new SP
- NewSS DW 0 ;Patched in with new SS
-
- Chain4 ENDP
-
- Dummy LABEL BYTE ;Used to measure code to move
-
- CSEG ENDS
-
- END