You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
571 lines
14 KiB
571 lines
14 KiB
;/*
|
|
; * Microsoft Confidential
|
|
; * Copyright (C) Microsoft Corporation 1991
|
|
; * All Rights Reserved.
|
|
; */
|
|
;*****************************************************************************
|
|
;*****************************************************************************
|
|
;UTILITY NAME: FORMAT.COM
|
|
;
|
|
;MODULE NAME: FOREXEC.SAL
|
|
;
|
|
;
|
|
;
|
|
; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
; ³EXEC_FS_FORMAT³
|
|
; ÀÄÂÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
|
; ³
|
|
; ³ÚÄÄÄÄÄÄ¿
|
|
; ôShrink³
|
|
; ³ÀÄÄÄÄÄÄÙ
|
|
; ³ÚÄÄÄÄÄÄÄÄÄÄ¿
|
|
; ôSetup_EXEC³
|
|
; ³ÀÄÄÄÄÄÄÄÄÄÄÙ
|
|
; ³ÚÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
; ôEXEC_ArgVÃÄÄÄÄÄÄÄÄÄÄ´EXEC_Program³
|
|
; ³ÀÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
|
; ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
; ôEXEC_Cur_DirectoryÃÄ´EXEC_Program³
|
|
; ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
|
; ³ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
|
; À´EXEC_RoutineÃÄÄÄÄÄÄÄ´Build_Path_And_EXECÃÄ´EXEC_Program³
|
|
; ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
|
;
|
|
; Change List: AN000 - New code DOS 3.3 spec additions
|
|
; AC000 - Changed code DOS 3.3 spec additions
|
|
;*****************************************************************************
|
|
;*****************************************************************************
|
|
|
|
title DOS 3.30 FORMAT EXEC Module
|
|
|
|
IF1
|
|
%OUT ASSEMBLING: DOS 3.3 FORMAT EXEC LOADER
|
|
%OUT
|
|
ENDIF
|
|
|
|
code segment public para 'code'
|
|
assume cs:code
|
|
code ends
|
|
|
|
;*****************************************************************************
|
|
; Include files
|
|
;*****************************************************************************
|
|
|
|
.xlist
|
|
|
|
INCLUDE FORCHNG.INC
|
|
INCLUDE FORMACRO.INC
|
|
INCLUDE SYSCALL.INC
|
|
INCLUDE FOREQU.INC
|
|
|
|
.list
|
|
|
|
;*****************************************************************************
|
|
; Public Data
|
|
;*****************************************************************************
|
|
|
|
Public Drive_Letter_Msg
|
|
|
|
;*****************************************************************************
|
|
; Public Routines
|
|
;*****************************************************************************
|
|
|
|
|
|
IF FSExec
|
|
|
|
Public EXEC_FS_Format
|
|
|
|
ENDIF ;FSExec ;end /FS: conditional
|
|
|
|
|
|
|
|
;***************************************************************************
|
|
; External Data Declarations
|
|
;***************************************************************************
|
|
|
|
extrn ExitStatus:Byte
|
|
extrn Fatal_Error:Byte
|
|
extrn FS_String_Buffer:Byte
|
|
extrn msgEXECFailure:Byte
|
|
extrn PSP_Segment:Word
|
|
extrn DriveToFormat:byte
|
|
|
|
;**************************************************************************
|
|
; Structures
|
|
;**************************************************************************
|
|
|
|
|
|
Exec_Block_Parms struc
|
|
Segment_Env dw 0
|
|
Offset_Command dw 0
|
|
Segment_Command dw 0
|
|
Offset_FCB1 dw 0
|
|
Segment_FCB1 dw 0
|
|
Offset_FCB2 dw 0
|
|
Segment_FCB2 dw 0
|
|
|
|
Exec_Block_Parms ends
|
|
|
|
|
|
;**************************************************************************
|
|
; Equates
|
|
;**************************************************************************
|
|
|
|
|
|
String_Done equ 0
|
|
No_Error equ 0
|
|
Error equ 1
|
|
Stderr equ 2
|
|
Stack_Space equ 02eh ; IBM addition ROM paras
|
|
|
|
;**************************************************************************
|
|
; PSP Area
|
|
;**************************************************************************
|
|
|
|
PSP segment public para 'DUMMY'
|
|
|
|
org 2Ch
|
|
PSP_ENV_SEGMENT label word
|
|
|
|
FCB1 equ 5Ch
|
|
|
|
FCB2 equ 6Ch
|
|
|
|
org 80h
|
|
Command_Line label byte
|
|
|
|
|
|
PSP ends
|
|
|
|
;**************************************************************************
|
|
; Data Area
|
|
;**************************************************************************
|
|
|
|
data segment public para 'DATA'
|
|
assume ds:data,es:nothing
|
|
|
|
Exec_Block Exec_Block_Parms <>
|
|
EXEC_Path db 66 dup(0)
|
|
|
|
Drive_Letter_Msg db "A:",0 ;Drive for exec fail message
|
|
|
|
SP_Save dw ?
|
|
SS_Save dw ?
|
|
|
|
|
|
;These next two should stay togather
|
|
; ---------------------------------------
|
|
|
|
Path_String db "PATH="
|
|
Len_Path_String equ $ - Path_String
|
|
|
|
;----------------------------------------
|
|
|
|
;These should stay togather
|
|
; ---------------------------------------
|
|
|
|
Search_FORMAT db "FORMAT"
|
|
Len_Search_FORMAT equ $ - Search_FORMAT
|
|
Search_Format_End equ $
|
|
|
|
;----------------------------------------
|
|
|
|
|
|
;These next two should stay togather
|
|
; ---------------------------------------
|
|
|
|
data ends
|
|
|
|
;**************************************************************************
|
|
|
|
code segment public para 'code'
|
|
assume cs:code,ds:data
|
|
|
|
;**************************************************************************
|
|
; Main Routine
|
|
;**************************************************************************
|
|
|
|
|
|
IF FSExec ;if /FS: desired
|
|
|
|
Procedure Exec_FS_Format
|
|
|
|
Set_Data_Segment
|
|
call Set_FCB1_Drive
|
|
call Shrink
|
|
mov al,ExitStatus ;Setblock fail?
|
|
|
|
cmp al,Error
|
|
JE $$IF1
|
|
call Setup_Exec
|
|
call Exec_Argv ;try exec from dir BASIC loaded
|
|
mov al,ExitStatus
|
|
|
|
cmp al,Error
|
|
JNE $$IF2
|
|
call Exec_Cur_Directory
|
|
mov al,ExitStatus ;Try exec from cur directory
|
|
|
|
cmp al,Error
|
|
JNE $$IF2
|
|
call EXEC_Routine
|
|
mov al,ExitStatus
|
|
|
|
cmp al,Error
|
|
JNE $$IF2
|
|
|
|
push ds ;save ds
|
|
push si ;save si
|
|
mov si,PSP_Segment ;get psp
|
|
mov ds,si ;put psp in ds
|
|
assume ds:PSP
|
|
|
|
mov si,FCB1 ;ptr to 1st. FCB
|
|
mov bl,byte ptr ds:[si] ;get drive ID
|
|
|
|
pop si ;restore si
|
|
pop ds ;restore ds
|
|
Set_Data_Segment ;set segments
|
|
|
|
cmp bl,0 ;Is it default drive?
|
|
JNE $$IF3
|
|
push ax ;Save exit code
|
|
DOS_Call Get_Default_Drive ;Get the default drive
|
|
add al,"A" ;Turn into drive letter
|
|
mov Drive_Letter_Msg,al ;Save it in message
|
|
pop ax ;Get return code back
|
|
|
|
JMP SHORT $$EN3
|
|
$$IF3:
|
|
add bl,"A"-1 ;Convert to drive letter
|
|
mov Drive_Letter_Msg,bl
|
|
|
|
$$EN3:
|
|
Message msgEXECFailure
|
|
JMP SHORT $$EN2
|
|
|
|
$$IF2:
|
|
DOS_Call WaitProcess
|
|
mov ExitStatus,al
|
|
|
|
$$EN2:
|
|
$$IF1:
|
|
mov Fatal_Error,YES ;Not really, indicates FS used
|
|
ret
|
|
|
|
Exec_FS_Format endp
|
|
|
|
;****************************************************************************
|
|
; Shrink
|
|
;****************************************************************************
|
|
|
|
Procedure Shrink
|
|
|
|
mov ax,cs ;get code segment
|
|
mov bx,ds ;get data segment
|
|
sub ax,bx ;data seg size
|
|
mov bx,ax ;save paras
|
|
mov ax,offset End_Program ;Get the offset of end of loader
|
|
mov cl,4 ;Div by 16 to get para's
|
|
shr ax,cl
|
|
add bx,ax ;add in code space
|
|
add bx,Stack_Space ;adjust for stack
|
|
add bx,11h ;give PSP space
|
|
mov ax,PSP_Segment
|
|
mov es,ax
|
|
assume es:nothing
|
|
|
|
DOS_Call SetBlock
|
|
JNC $$IF9
|
|
Message msgEXECFailure
|
|
mov ExitStatus,Error ;Bad stuff, time to quit
|
|
$$IF9:
|
|
ret
|
|
|
|
Shrink endp
|
|
|
|
;**************************************************************************
|
|
; Setup_Exec
|
|
;**************************************************************************
|
|
|
|
Procedure Setup_Exec
|
|
|
|
Set_Data_Segment
|
|
mov ax,PSP_Segment ;Get segment of PSP
|
|
mov ds,ax
|
|
|
|
assume ds:PSP
|
|
;Setup dword pointer to command line to be passed
|
|
|
|
mov es:Exec_Block.Segment_Command,ax ;Segment for command line
|
|
mov es:Exec_Block.Offset_Command,offset ds:Command_Line
|
|
|
|
;Setup dword pointer to first FCB to be passed
|
|
|
|
mov es:Exec_Block.Segment_FCB1,ax ;Segment for FCB1
|
|
mov es:Exec_Block.Offset_FCB1,offset ds:FCB1 ;Offset of FCB at 05Ch
|
|
|
|
;Setup dword pointer to second FCB to be passed ;
|
|
|
|
mov es:Exec_Block.Segment_FCB2,ax ;Segment for FCB2
|
|
mov es:Exec_Block.Offset_FCB2,offset ds:FCB2 ;Offset of FCB at 06Ch
|
|
|
|
;Setup segment of Environment string, get from PSP ;
|
|
|
|
mov ax,ds:PSP_Env_Segment
|
|
mov es:Exec_Block.Segment_Env,ax
|
|
Set_Data_Segment
|
|
ret
|
|
|
|
|
|
Setup_EXEC endp
|
|
|
|
;****************************************************************************
|
|
; Exec_Argv
|
|
;****************************************************************************
|
|
;
|
|
; Read the environment to get the Argv(0) string, which contains the drive,
|
|
; path and filename that was loaded for FORMAT.COM. This will be used to find
|
|
; the xxxxxfmt.exe, assuming that it is in the same location or path as
|
|
; FORMAT.COM
|
|
;
|
|
|
|
Procedure EXEC_Argv
|
|
|
|
Set_Data_Segment ;DS,ES = DATA
|
|
cld
|
|
mov ax,Exec_Block.Segment_Env ;Get the environment
|
|
mov ds,ax ;Get addressability
|
|
|
|
assume ds:nothing
|
|
|
|
xor si,si ;Start at beginning
|
|
$$DO11:
|
|
$$DO12:
|
|
inc si ;Get character
|
|
cmp byte ptr [si-1],0 ;Find string seperator?
|
|
JNE $$DO12
|
|
inc si ;Get next char
|
|
cmp byte ptr [si-1],0 ;Are we at Argv(0)? (00?)
|
|
JNE $$DO11
|
|
add si,2 ;Skip the word count
|
|
mov di,si ;Save where string starts
|
|
|
|
$$DO15: ;Find length of Argv(0) string
|
|
inc si ;Get char
|
|
cmp byte ptr [si-1],0 ;Is it the end?
|
|
;End found if 0 found
|
|
JNE $$DO15
|
|
mov cx,si ;Get number of bytes in string
|
|
sub cx,di ;Put in cx reg for rep count
|
|
mov si,di ;Point to path
|
|
mov di,offset es:EXEC_Path ;Point to where to put it
|
|
rep movsb ;Move the string
|
|
Set_Data_Segment
|
|
dec di ;Point at end of ArgV string
|
|
std ;Look backwards
|
|
|
|
$$DO17: ;Find 'FORMAT' in ARGV string
|
|
mov cx,Len_Search_FORMAT ;Get length to compare
|
|
mov si,offset Search_FORMAT_End-1 ;Look at comp string from end
|
|
repe cmpsb ;See if same string
|
|
|
|
|
|
JNE $$DO17
|
|
mov si,offset FS_String_Buffer
|
|
inc di ;DI = replacement point-1
|
|
cld ;Set direction flag back
|
|
mov cx,Len_FS_String_Buffer ;Length of string to move
|
|
rep movsb ;Build part of the path
|
|
call EXEC_Program
|
|
ret
|
|
|
|
EXEC_ArgV endp
|
|
|
|
;****************************************************************************
|
|
; EXEC_Program
|
|
;****************************************************************************
|
|
|
|
Procedure EXEC_Program
|
|
|
|
Set_Data_Segment
|
|
mov ExitStatus,No_Error ;Setup to Exec the file
|
|
mov dx,offset Exec_Path
|
|
mov bx,offset Exec_Block
|
|
mov al,0
|
|
mov word ptr SP_Save,sp ;save sp
|
|
mov word ptr SS_Save,ss ;save ss
|
|
|
|
DOS_Call Exec
|
|
|
|
cli ;turn off int's
|
|
mov sp,word ptr SP_Save ;retrieve sp
|
|
mov ss,word ptr SS_Save ;retrieve ss
|
|
sti ;turn on int's
|
|
|
|
|
|
; $IF C ;CY means failure
|
|
JNC $$IF19
|
|
mov ExitStatus,Error ;Set error code
|
|
; $ENDIF
|
|
$$IF19:
|
|
ret
|
|
|
|
EXEC_Program endp
|
|
|
|
|
|
;****************************************************************************
|
|
; EXEC_Routine
|
|
;****************************************************************************
|
|
|
|
Procedure EXEC_Routine
|
|
|
|
Set_Data_Segment
|
|
mov ExitStatus,Error ;Assume the worst
|
|
cld
|
|
push ds
|
|
mov ax,Exec_Block.Segment_Env ;Get the environment
|
|
mov ds,ax ;Get addressability
|
|
assume ds:nothing
|
|
|
|
xor si,si ;Start at beginning
|
|
; $SEARCH
|
|
$$DO21:
|
|
cmp word ptr ds:[si],0 ;End of the Evironment?
|
|
; $EXITIF E ;Reached end, no more look
|
|
JNE $$IF21
|
|
|
|
; $ORELSE ;Look for 'PATH=' in environment
|
|
JMP SHORT $$SR21
|
|
$$IF21:
|
|
mov di,offset Path_String
|
|
mov cx,Len_Path_String
|
|
repe cmpsb
|
|
; $LEAVE E ;Found if EQ
|
|
JE $$EN21
|
|
; $ENDLOOP ;Found PATH in environment
|
|
JMP SHORT $$DO21
|
|
$$EN21:
|
|
call Build_Path_And_Exec
|
|
; $ENDSRCH
|
|
$$SR21:
|
|
pop ds
|
|
ret
|
|
|
|
EXEC_Routine endp
|
|
|
|
;****************************************************************************
|
|
; Build_Path_For_EXEC
|
|
;****************************************************************************
|
|
|
|
Procedure Build_Path_And_Exec
|
|
|
|
$$DO27:
|
|
cmp byte ptr ds:[si],0 ;All path entries done?
|
|
|
|
JE $$IF28
|
|
mov di,offset EXEC_Path ;Point at where to put path
|
|
mov byte ptr es:[di],0 ;End path just in case
|
|
|
|
$$DO29:
|
|
cmp byte ptr ds:[si],0 ;End of Path?
|
|
|
|
JE $$EN29
|
|
cmp byte ptr ds:[si],';' ;End of entry?
|
|
|
|
JNE $$IF31
|
|
inc si ;point to next character
|
|
jmp EXIT_BPE_LOOP ;exit loop
|
|
|
|
$$IF31:
|
|
movsb ;Put char in path string
|
|
|
|
JMP SHORT $$DO29
|
|
$$EN29:
|
|
|
|
EXIT_BPE_LOOP:
|
|
;Path filled in,get backslash
|
|
cmp byte ptr ds:[si-1],0 ;Any path there?
|
|
|
|
JE $$IF34
|
|
;Nope
|
|
cmp byte ptr ds:[si-1],"\" ;Need a backslash? ;
|
|
|
|
JE $$IF35
|
|
mov byte ptr es:[di],"\" ;Yes, put one in ;
|
|
inc di ;Line it up for next stuff
|
|
inc si
|
|
|
|
$$IF35:
|
|
push si ;Save place in path
|
|
push ds ;Save segment for environment
|
|
push es ;Xchange ds/es
|
|
pop ds
|
|
mov si,offset FS_String_Buffer ;Fill in filename
|
|
mov cx, Len_FS_String_Buffer
|
|
rep movsb
|
|
call Exec_Program
|
|
cmp ExitStatus,No_Error ;E if EXEC okay
|
|
pop ds ;Get Env segment back
|
|
pop si ;Get place in path back
|
|
|
|
$$IF34:
|
|
$$IF28:
|
|
|
|
JNE $$DO27
|
|
ret
|
|
|
|
Build_Path_And_EXEC Endp
|
|
|
|
;**************************************************************************
|
|
; Exec_Cur_Directory
|
|
;**************************************************************************
|
|
|
|
Procedure Exec_Cur_Directory
|
|
|
|
Set_Data_Segment
|
|
mov si,offset FS_String_Buffer ;Setup path for current dir
|
|
mov di,offset EXEC_Path
|
|
mov cx,Len_FS_String_Buffer
|
|
rep movsb
|
|
call EXEC_Program
|
|
ret
|
|
|
|
EXEC_Cur_Directory endp
|
|
|
|
;=========================================================================
|
|
; Set_FCB1_Drive : This routine sets the 1st. byte of the FCB1,
|
|
; the drive identifier, to the default drive.
|
|
;=========================================================================
|
|
|
|
Procedure Set_FCB1_Drive ;set drive ID
|
|
|
|
push ds ;save ds
|
|
push si ;save si
|
|
|
|
mov si,PSP_Segment ;get segment of PSP
|
|
mov ds,si ;put it in ds
|
|
assume ds:PSP
|
|
mov si,FCB1 ;ptr to FCB1
|
|
mov byte ptr ds:[si],00h ;set drive ID to
|
|
; default drive
|
|
pop si ;restore si
|
|
pop ds ;restore ds
|
|
Set_Data_Segment ;set up segmentation
|
|
ret
|
|
|
|
Set_FCB1_Drive endp
|
|
|
|
ENDIF ;FSExec ;end /FS: conditional
|
|
;assembly
|
|
|
|
;**************************************************************************
|
|
|
|
public End_Program
|
|
End_Program label byte
|
|
|
|
;**************************************************************************
|
|
|
|
code ends
|
|
end
|
|
|