home *** CD-ROM | disk | FTP | other *** search
- DATA SEGMENT WORD PUBLIC
-
- EXTRN PrefixSeg:WORD
- EXTRN SaveInt00:DWORD
- EXTRN SaveInt02:DWORD
- EXTRN SaveInt23:DWORD
- EXTRN SaveInt24:DWORD
- EXTRN SaveInt75:DWORD
-
- DATA ENDS
-
- CODE SEGMENT BYTE PUBLIC
-
- ASSUME CS:Code,DS:Data
-
- PUBLIC Chain4
-
- ;This generates a bunch of NOPs in object
- ;CodeLen = offset Dummy-offset CodeToRelocate ;Length of code in PSP
- ;MaxCmdLen = 07Eh-CodeLen ;Maximum length of command line
-
- ;These values must be exact
- ;They'll need changing if anything after label CodeToRelocate changes
- CodeLen EQU 01Fh
- MaxCmdLen EQU 05Fh
-
- ;**************************************************************** Chain4
- ; procedure Chain4(Path, CmdLine : String);
- ; Turbo 4 equivalent of chaining
-
- ;Parameters
- PathArg EQU DWORD PTR [BP+10]
- CmdLine EQU DWORD PTR [BP+6]
-
- ;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]
- 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:Data
- Error1: MOV SP,BP ;Return with error code in AX
- POP BP ;Restore BP
- RET 8 ;Remove parameters from stack
-
- ;Read header and close file
- 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,CX
- MOV AX,30 ;Prepare for Read Fault error
- JNE Error ;Error if 28 bytes not read
- MOV AH,3Eh ;Close file
- INT 21h
- JC Error ;Error if carry set
-
- ;Allocate all available memory to this process
- POP DS ;Restore DS
- ASSUME DS:Data
- MOV ES,PrefixSeg ;Main program segment
- MOV AH,4Ah ;Setblock
- MOV BX,0FFFFh ;Ask for everything
- INT 21h
- 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 segment
- MOV CS:TmpSS,AX ;Store temporary SS
-
- ;Close secondary file handles (don't touch StdIn,StdOut,StdErr)
- MOV BX,3 ;Start with handle 3
- MOV CX,17 ;17 handles max
- NextHandle:
- MOV AH,3Eh ;DOS close file
- INT 21h
- INC BX ;Ignore errors
- LOOP NextHandle
-
- ;Restore interrupt vectors taken over by SYSTEM library
- MOV CX,DS ;Save DS
- MOV AX,2500h ;Restore INT 00
- LDS DX,SaveInt00 ;Get saved vector
- ASSUME DS:Nothing
- INT 21h
-
- MOV DS,CX ;Restore DS
- ASSUME DS:Data
- MOV AL,02h ;Restore INT 02
- LDS DX,SaveInt02 ;Get saved vector
- ASSUME DS:Nothing
- INT 21h
-
- MOV DS,CX ;Restore DS
- ASSUME DS:Data
- MOV AL,23h ;Restore INT 23
- LDS DX,SaveInt23 ;Get saved vector
- ASSUME DS:Nothing
- INT 21h
-
- MOV DS,CX ;Restore DS
- ASSUME DS:Data
- MOV AL,24h ;Restore INT 24
- LDS DX,SaveInt24 ;Get saved vector
- ASSUME DS:Nothing
- INT 21h
-
- MOV DS,CX ;Restore DS
- ASSUME DS:Data
- MOV AL,75h ;Restore INT 75
- LDS DX,SaveInt75 ;Get saved vector
- ASSUME DS:Nothing
- INT 21h
-
- ;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
- 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 ; write to code in PSP
- 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 executed in PSP
- CodeToRelocate:
- INT 21h ;Call DOS EXEC
- JNC GoodLoad ;Check for error
- INT 20h ;Error shouldn't happen,
- ; just halt if EXEC failed
- GoodLoad:
- MOV AX,CS ;Get base of program
- MOV DS,AX ;Initialize DS
- MOV ES,AX ;Initialize ES
- 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
-
- CODE ENDS
-
- END