ReC98/libs/BorlandC/exec.asm

494 lines
15 KiB
NASM
Raw Normal View History

; *Not* the original file, but an edit to turn it into an includable slice.
; Changes include:
; * removal of RULES.ASI to eliminate redundancy
; * removal of external data declarations
; * removal of the segment macro references (for obvious reasons)
; * and a section of code in CopyPathName, where the Japanese / PC-98 version
; of the Borland C runtime verifies the executable type in advance, and also
; checks the entire file extension rather than just its first letter
; (presumably to eliminate false positives when dealing with Shift-JIS).
;[]-----------------------------------------------------------------[]
;| EXEC.ASM -- Execute a program with Overlay |
;[]-----------------------------------------------------------------[]
;
; C/C++ Run Time Library - Version 5.0
;
; Copyright (c) 1987, 1992 by Borland International
; All Rights Reserved.
;
;* Miscellaneous equates */
ExeSignature equ 05A4Dh
;/* Data for the Loader */
LdDesc STRUC
LdErrorMsg db 'Exec failure.',00Dh,00Ah
LdStack db 80H dup(?) ;Loader stack
LdPSP dw ? ;PSP address
LdPathName db 80 dup(?) ;File to be loaded
LdAX dw ? ;Parse file name results
LdExeSignature dw ? ;EXE header buffer
LdLength dw ?
LdNbPages dw ?
LdNbItems dw ?
LdHdrSize dw ?
LdMin dw ?
LdMax dw ?
LdSS dw ?
LdSP dw ?
LdCheckSum dw ?
LdIP dw ?
LdCS dw ?
LdLoadAddr dw ? ;Load Overlay interface block
LdRelocFactor dw ? ;Relocation factor to be used
LdDesc ENDS
SUBTTL Loader program
PAGE
;/* */
;/*------------------------------------------------------*/
;/* */
;/* Loader Program */
;/* -------------- */
;/* */
;/*------------------------------------------------------*/
;/* */
LoaderDatas db size LdDesc dup (0)
_Loader PROC NEAR ;CX = EnvSeg, DX = End of Memory
;/* Setup segment registers */
xor di, di
mov ax, cs
mov ds, ax
mov es, ax
cli
mov ss, ax
lea sp, [di+LdPSP]
sti
;/* Load The Program */
push cx
push dx
mov ax, 4B03h
lea bx, [di+LdLoadAddr]
lea dx, [di+LdPathName]
int 21h
pop dx
pop cx
jb LoadError
xor di, di
cli
mov ss, [di+LdSS]
mov sp, [di+LdSP]
sti
mov bp, sp
xor ax, ax
push ax ;Return to MSDOS for .COM
mov ax, [di+LdPSP]
mov ds, ax
mov es, ax
mov es:[2h], dx ;Set End of Program into PSP
mov es:[2ch], cx ;Set EnvSeg into PSP
mov ax, cs:[di+LdAX] ;AX = validity of FCBs
jmp dword ptr cs:[LdIP]
;/* Fatal Error if unable to load the program */
LoadError label near
mov ah, 040h
mov bx, 2
mov cx, LdStack - LdErrorMsg
xor dx, dx
int 21h ;Error message on stderr
mov ax, 4C02h
int 21h ;exit(2)
_Loader ENDP
LoaderSize equ ($ - LoaderDatas + 15) / 16
wLoaderSize equ LoaderSize * 8
LoaderVector dd _Loader - LoaderDatas
SUBTTL Loader program
PAGE
;/* */
;/*------------------------------------------------------*/
;/* */
;/* int _exec(pathP, cmdP, envP); */
;/* char *pathP; */
;/* char *cmdP; */
;/* char *envP; */
;/* */
;/*------------------------------------------------------*/
;/* */
pathP equ 4
IF LDATA
cmdP equ pathP + 4
envP equ cmdP + 4
ELSE
cmdP equ pathP + 2
envP equ cmdP + 2
ENDIF
FileHandle equ 2
MemSize equ FileHandle + 2
EnvSize equ MemSize + 2
EnvAddr equ EnvSize + 4
OldEnv equ EnvAddr + 2
OldEnvSave dw ?
UseOldEnv db 1 ;flag, defaults to true
public __exec
__exec proc near
push bp
mov bp, sp
sub sp, OldEnv
cld
push si
push ds
push di
push es
IFDEF __HUGE__
mov ds, cs:DGROUP@@ ; Get DS if we're huge
ENDIF
mov ax,__envseg ;save old environment
mov cs:OldEnvSave,ax
;/* Open the file to be loaded */
mov ax, 3d00h
pushDS_
LDS_ dx, [bp+pathP]
int 21h
popDS_
mov [bp-FileHandle], ax
jnb CopyCmdLine
jmp ExecExit
;/* Copy the command line into the PSP */
CopyCmdLine label near
IFDEF __HUGE__
mov ax, seg _psp@
mov ds, ax
ENDIF
mov es, _psp@
mov LoaderDatas.LdPSP, es
mov ax, es:[2ch]
mov [bp-OldEnv], ax
mov di, 080h
pushDS_
LDS_ si, [bp+cmdP]
lodsb
mov dx, si ;Save cmdP for parse
stosb
xor cx, cx
mov cl, al
inc cx
rep movsb
;/* Parse the command line for FCBs */
mov ax, 2901h
mov si, dx
mov di, 05ch
int 21h ;Build FCB 1 in PSP
mov byte ptr LoaderDatas.LdAX, al
FindWhite label near
mov al,[si]
cmp al,20h ; Space
je NextFCB
cmp al,09h ; Tab
je NextFCB
cmp al,0dh ; Carriage Return
je NextFCB
inc si
jmp FindWhite
NextFCB label near
mov ax, 2901h
mov di, 06ch
int 21h ;Build FCB 2 in PSP
mov byte ptr LoaderDatas.LdAX+1, al
popDS_
;/* Get the maximum memory block size */
mov ah, 4Ah
mov bx, -1
int 21h
cmp byte ptr _version@, 3
jnb GetMaxMem
sub bx, 280h
GetMaxMem label near
mov [bp-MemSize], bx
;/* Compute environment size */
IF LDATA
mov ax, [bp+envP]
mov dx, [bp+envP+2]
ELSE
mov ax, [bp+envP]
or ax, ax
mov dx, ds
jnz DoWeHaveAnEnv
cwd
ENDIF
DoWeHaveAnEnv label near
mov bx, ax
or bx, dx
jnz WeHaveAnEnv
xor ax, ax
mov di, ax
jmp short SetEnvSize
WeHaveAnEnv label near
mov es, dx
mov di, ax
push di
mov cx, -1
xor ax, ax
GetEnvSize label near
repnz scasb
cmp es:[di], al
jne GetEnvSize
dec cx
add di, 3
repnz scasb ;/* EnvSize += PathSize */
dec cx
mov ax, cx
neg ax
pop di
SetEnvSize label near
mov [bp-EnvAddr], di
mov [bp-EnvAddr+2], es
add ax, 15
mov cx, 4
shr ax, cl
mov [bp-EnvSize], ax
mov si,__envseg ;get the arena header for the environ
dec si
mov es,si
cmp ax,word ptr es:[03] ;can we use the orig environ?
jbe SavePath
dec cs:UseOldEnv ;set to false
inc ax
sub [bp-MemSize], ax ;Reserve space for Env
;/* Save the pathname of the file to be loaded */
SavePath label near
LDS_ si, [bp+pathP]
push cs
pop es
lea di, LoaderDatas.LdPathName
CopyPathName label near
lodsb
stosb
or al, al
jnz CopyPathName
;/* Process the file according to its type */
mov bx, [bp-FileHandle]
; PC-98 / Japanese-specific code below...
; ---
push ds
pop es
push cs
pop ds
mov di, offset LoaderDatas
mov ah, 3fh
mov cx, LdLoadAddr - LdExeSignature
lea dx, [di+LdExeSignature]
int 21h
jb ExecError
cmp [di+LdExeSignature], ExeSignature
jz EXEFile
mov ax, es:[si-5]
or ah, ' ' ; one space
cmp ax, 'c.'
jnz NoExec
mov ax, es:[si-3]
or ax, ' ' ; two spaces
cmp ax, 'mo'
jnz NoExec
jmp COMFile
NoExec label near
mov ax, 11
;/* Here comes all Exec Error */
ExecError label near
push ax
mov ah, 3eh
mov bx, [bp-FileHandle]
int 21h
pop ax
jmp ExecExit
;/* This file must be an .EXE file */
EXEFile label near
mov ax, [di+LdNbPages]
xor dx, dx
mov dl, ah
mov ah, al
xor al, al
shl ax, 1
rcl dx, 1 ;DX:AX = NbPages * 512
add ax, [di+LdLength]
adc dx, 0
mov cx, 4
EXECompute label near
shr dx, 1
rcr ax, 1
loop EXECompute
inc ax
sub ax, [di+LdHdrSize]
add ax, [di+LdMin]
xchg bx, ax
mov ax, [di+LdPSP]
add ax, 16
add [di+LdCS], ax
add [di+LdSS], ax
xchg ax, bx
jmp short IsItEnough
;/* The file to be loaded is .COM file */
COMFile label near
mov ax, 4202h
xor cx, cx
xor dx, dx
int 21h
mov cx, 4
COMCompute label near
shr dx, 1
rcr ax, 1
loop COMCompute
inc ax
xchg bx, ax
mov ax, [di+LdPSP]
mov [di+LdCS], ax
mov [di+LdIP], 0100h
mov [di+LdSS], ax
add ax, 16
xchg ax, bx
IsItEnough label near ;AX = Pgm requirements, BX = Pgm Load Addr
mov [di+LdLoadAddr], bx
mov [di+LdRelocFactor], bx
add ax, LoaderSize
cmp ax, [bp-MemSize]
mov ax, 8
jna $+5
jmp ExecError
;/* Close the file before load it */
mov ah, 3eh
mov bx, [bp-FileHandle]
int 21h
;/* Takes all the memory above the current program */
mov es, [di+LdPSP]
mov ah, 4ah
mov bx, [bp-MemSize]
int 21h
jnb $+5
jmp ExecError
;/* Move the Loader before loading the overlay */
add bx, [di+LdPSP]
mov dx, bx ;Save end of memory
sub bx, LoaderSize+1
mov word ptr LoaderVector+2, bx
mov es, bx
mov cx, wLoaderSize
mov si, offset LoaderDatas
xor di, di
rep movsw
;/* Copy the environment */
mov es, [bp-OldEnv]
mov cx, [bp-EnvSize]
cmp cs:UseOldEnv,0
jne ReUseEnv
mov ah, 48h
mov bx, cx
int 21h
jb ExecExit
jmp short CopyEnv
ReUseEnv: mov ax, cs:OldEnvSave
CopyEnv: mov es, ax
xor di, di
lds si, [bp-EnvAddr]
add cx, cx
add cx, cx
add cx, cx
rep movsw
push es
;/* Call exit procedures. Note: do not close file handles */
;/* Once we do this we can't go back! */
push dx
push ds
mov ds, cs:DGROUP@@ ; Get DS
nopcall __cexit
pop ds
pop dx
;/* Free the old environment space */
cmp cs:UseOldEnv,0
jne ReadyToOverlay
mov es, cs:OldEnvSave
mov ah, 49h
int 21h
;/* Jump to Loader and overlay the current program */
ReadyToOverlay label near
pop cx
jmp LoaderVector
;/* All error conditions set _doserrno and errno */
ExecExit label near
pop es
pop di
pop ds
pop si
push ax
call __IOERROR
mov sp, bp
pop bp
ret
__exec endp