mirror of
https://github.com/microsoft/MS-DOS.git
synced 2024-12-03 11:05:47 +00:00
2166 lines
63 KiB
NASM
2166 lines
63 KiB
NASM
|
; COMMAND version 1.17
|
|||
|
;
|
|||
|
; This version of COMMAND is divided into three distinct parts. First
|
|||
|
; is the resident portion, which includes handlers for interrupts
|
|||
|
; 22H (terminate), 23H (Cntrl-C), 24H (fatal error), and 27H (stay
|
|||
|
; resident); it also has code to test and, if necessary, reload the
|
|||
|
; transient portion. Following the resident is the init code, which is
|
|||
|
; overwritten after use. Then comes the transient portion, which
|
|||
|
; includes all command processing (whether internal or external).
|
|||
|
; The transient portion loads at the end of physical memory, and it may
|
|||
|
; be overlayed by programs that need as much memory as possible. When
|
|||
|
; the resident portion of command regains control from a user program,
|
|||
|
; a checksum is performed on the transient portion to see if it must be
|
|||
|
; reloaded. Thus programs which do not need maximum memory will save
|
|||
|
; the time required to reload COMMAND when they terminate.
|
|||
|
|
|||
|
;Use the following booleans to set assembly flags
|
|||
|
FALSE EQU 0
|
|||
|
TRUE EQU NOT FALSE
|
|||
|
|
|||
|
IBMVER EQU FALSE ;Switch to build IBM version of Command
|
|||
|
MSVER EQU TRUE ;Switch to build MS-DOS version of Command
|
|||
|
|
|||
|
HIGHMEM EQU TRUE ;Run resident part above transient (high memory)
|
|||
|
|
|||
|
LINPERPAG EQU 23
|
|||
|
NORMPERLIN EQU 1
|
|||
|
WIDEPERLIN EQU 5
|
|||
|
|
|||
|
IF IBMVER
|
|||
|
SYM EQU ">"
|
|||
|
COMDRV EQU 1
|
|||
|
ENDIF
|
|||
|
|
|||
|
IF MSVER
|
|||
|
SYM EQU ":"
|
|||
|
COMDRV EQU 0
|
|||
|
ENDIF
|
|||
|
|
|||
|
FCB EQU 5CH
|
|||
|
DSKRESET EQU 13
|
|||
|
SETBASE EQU 38
|
|||
|
SRCHFRST EQU 17
|
|||
|
SRCHNXT EQU 18
|
|||
|
RENAM EQU 23
|
|||
|
INCHAR EQU 1
|
|||
|
GETFAT EQU 27
|
|||
|
OPEN EQU 15
|
|||
|
CLOSE EQU 16
|
|||
|
MAKE EQU 22
|
|||
|
DELETE EQU 19
|
|||
|
RDBLK EQU 39
|
|||
|
WRBLK EQU 40
|
|||
|
SETDMA EQU 26
|
|||
|
SELDRV EQU 14
|
|||
|
GETDRV EQU 25
|
|||
|
PRINTBUF EQU 9
|
|||
|
OUTCH EQU 2
|
|||
|
INBUF EQU 10
|
|||
|
GETDATE EQU 2AH
|
|||
|
SETDATE EQU 2BH
|
|||
|
GETTIME EQU 2CH
|
|||
|
SETTIME EQU 2DH
|
|||
|
RR EQU 33
|
|||
|
RECLEN EQU 14
|
|||
|
FILLEN EQU 16
|
|||
|
OFFDATE EQU 20
|
|||
|
|
|||
|
|
|||
|
;The following are all of the segments used in the load order
|
|||
|
|
|||
|
CODERES SEGMENT
|
|||
|
CODERES ENDS
|
|||
|
|
|||
|
DATARES SEGMENT BYTE
|
|||
|
DATARES ENDS
|
|||
|
|
|||
|
INIT SEGMENT BYTE
|
|||
|
INIT ENDS
|
|||
|
|
|||
|
TAIL SEGMENT PARA
|
|||
|
TAIL ENDS
|
|||
|
|
|||
|
TRANCODE SEGMENT PARA
|
|||
|
TRANCODE ENDS
|
|||
|
|
|||
|
TRANDATA SEGMENT BYTE
|
|||
|
TRANDATA ENDS
|
|||
|
|
|||
|
TRANSPACE SEGMENT BYTE
|
|||
|
TRANSPACE ENDS
|
|||
|
|
|||
|
RESGROUP GROUP CODERES,DATARES,INIT,TAIL
|
|||
|
TRANGROUP GROUP TRANCODE,TRANDATA,TRANSPACE
|
|||
|
|
|||
|
;Data for resident portion
|
|||
|
|
|||
|
DATARES SEGMENT BYTE
|
|||
|
ORG 0
|
|||
|
ZERO = $
|
|||
|
MESBAS DW OFFSET RESGROUP:ERR0
|
|||
|
DW OFFSET RESGROUP:ERR2
|
|||
|
DW OFFSET RESGROUP:ERR4
|
|||
|
DW OFFSET RESGROUP:ERR6
|
|||
|
DW OFFSET RESGROUP:ERR8
|
|||
|
DW OFFSET RESGROUP:ERR10
|
|||
|
DW OFFSET RESGROUP:ERR12
|
|||
|
ERR0 DB "Write protect$"
|
|||
|
ERR2 DB "Not ready$"
|
|||
|
ERR4 DB "Data$"
|
|||
|
ERR6 DB "Seek$"
|
|||
|
ERR8 DB "Sector not found$"
|
|||
|
ERR10 DB "Write fault$"
|
|||
|
ERR12 DB "Disk$"
|
|||
|
READ DB "read$"
|
|||
|
WRITE DB "writ$"
|
|||
|
ERRMES DB " error "
|
|||
|
IOTYP DB "writing"
|
|||
|
DRVNUM DB " drive "
|
|||
|
DRVLET DB "A"
|
|||
|
NEWLIN DB 13,10,"$"
|
|||
|
REQUEST DB "Abort, Retry, Ignore? $"
|
|||
|
BADFAT DB 13,10,"File allocation table bad,$"
|
|||
|
COMBAD DB 13,10,"Invalid COMMAND.COM"
|
|||
|
NEEDCOM DB 13,10,"Insert DOS disk in "
|
|||
|
IF IBMVER
|
|||
|
DB "drive A"
|
|||
|
ELSE
|
|||
|
DB "default drive"
|
|||
|
ENDIF
|
|||
|
PROMPT DB 13,10,"and strike any key when ready",13,10,"$"
|
|||
|
NEEDBAT DB 13,10,"Insert disk with batch file$"
|
|||
|
ENDBATMES DB 13,10,"Terminate batch job (Y/N)? $"
|
|||
|
LOADING DB 0
|
|||
|
BATFCB DB 1,"AUTOEXECBAT"
|
|||
|
DB 21 DUP(?)
|
|||
|
DW 0
|
|||
|
DW 0 ;Initialize RR field to zero
|
|||
|
PARMTAB DW 10 DUP(-1) ;No parameters initially
|
|||
|
BATCH DB 1 ;Assume batch mode initially
|
|||
|
COMFCB DB COMDRV,"COMMAND COM"
|
|||
|
DB 25 DUP(?)
|
|||
|
TRANS DW OFFSET TRANGROUP:COMMAND
|
|||
|
TRNSEG DW ?
|
|||
|
BATBYT DB ?
|
|||
|
MEMSIZ DW ?
|
|||
|
SUM DW ?
|
|||
|
INITADD DB 4 DUP(?)
|
|||
|
RESDATASIZE EQU $-ZERO
|
|||
|
DATARES ENDS
|
|||
|
|
|||
|
;Data for transient portion
|
|||
|
|
|||
|
TRANDATA SEGMENT BYTE
|
|||
|
ORG 0
|
|||
|
ZERO EQU $
|
|||
|
BADNAM DB "Bad command or file name",13,10,"$"
|
|||
|
MISNAM DB "Missing file name$"
|
|||
|
RENERR DB "Duplicate file name or "
|
|||
|
NOTFND DB "File not found$"
|
|||
|
EXEBAD DB "Error in EXE file$"
|
|||
|
NOSPACE DB "Insufficient disk space",13,10,"$"
|
|||
|
FULDIR DB "File creation error",13,10,"$"
|
|||
|
OVERWR DB "File cannot be copied onto itself",13,10,"$"
|
|||
|
LOSTERR DB "Content of destination lost before copy",13,10,"$"
|
|||
|
COPIED DB " File(s) copied$"
|
|||
|
DIRMES DB " File(s)$"
|
|||
|
TOOBIG DB "Program too big to fit in memory$"
|
|||
|
BADDRV DB "Invalid drive specification$"
|
|||
|
PAUSMES DB "Strike a key when ready . . . $"
|
|||
|
BADSWT DB "Illegal switch",13,10,"$"
|
|||
|
WEEKTAB DB "SunMonTueWedThuFriSat"
|
|||
|
BADDAT DB 13,10,"Invalid date$"
|
|||
|
CURDAT DB "Current date is $"
|
|||
|
NEWDAT DB 13,10,"Enter new date: $"
|
|||
|
BADTIM DB 13,10,"Invalid time$"
|
|||
|
CURTIM DB "Current time is $"
|
|||
|
NEWTIM DB 13,10,"Enter new time: $"
|
|||
|
SUREMES DB "Are you sure (Y/N)? $"
|
|||
|
|
|||
|
COMTAB DB 4,"DIR",1
|
|||
|
DW OFFSET TRANGROUP:CATALOG
|
|||
|
DB 7,"RENAME",1
|
|||
|
DW OFFSET TRANGROUP:RENAME
|
|||
|
DB 4,"REN",1
|
|||
|
DW OFFSET TRANGROUP:RENAME
|
|||
|
DB 6,"ERASE",1
|
|||
|
DW OFFSET TRANGROUP:ERASE
|
|||
|
DB 4,"DEL",1
|
|||
|
DW OFFSET TRANGROUP:ERASE
|
|||
|
DB 5,"TYPE",1
|
|||
|
DW OFFSET TRANGROUP:TYPEFIL
|
|||
|
DB 4,"REM",1
|
|||
|
DW OFFSET TRANGROUP:COMMAND
|
|||
|
DB 5,"COPY",1
|
|||
|
DW OFFSET TRANGROUP:COPY
|
|||
|
DB 6,"PAUSE",1
|
|||
|
DW OFFSET TRANGROUP:PAUSE
|
|||
|
DB 5,"DATE",0
|
|||
|
DW OFFSET TRANGROUP:DATE
|
|||
|
DB 5,"TIME",0
|
|||
|
DW OFFSET TRANGROUP:TIME
|
|||
|
DB 0 ;Terminate command table
|
|||
|
|
|||
|
COMBUF DB 128,1,13
|
|||
|
|
|||
|
TRANDATASIZE EQU $-ZERO
|
|||
|
TRANDATA ENDS
|
|||
|
|
|||
|
;Uninitialized transient data
|
|||
|
TRANSPACE SEGMENT BYTE
|
|||
|
ORG 0
|
|||
|
ZERO = $
|
|||
|
DB 128 DUP(?)
|
|||
|
TPA DW 1 DUP(?)
|
|||
|
RESSEG DW 1 DUP(?)
|
|||
|
CHKDRV DB 1 DUP(?)
|
|||
|
FILTYP DB 1 DUP(?)
|
|||
|
CURDRV DB 1 DUP(?)
|
|||
|
PARM1 DB 1 DUP(?)
|
|||
|
PARM2 DB 1 DUP(?)
|
|||
|
COMSW DW 1 DUP(?)
|
|||
|
ARG1S DW 1 DUP(?)
|
|||
|
ARG2S DW 1 DUP(?)
|
|||
|
FLAGER DB 1 DUP(?)
|
|||
|
CFLAG DB 1 DUP(?)
|
|||
|
SPECDRV DB 1 DUP(?)
|
|||
|
BYTCNT DW 1 DUP(?)
|
|||
|
NXTADD DW 1 DUP(?)
|
|||
|
LINCNT DB 1 DUP(?)
|
|||
|
LINLEN DB 1 DUP(?)
|
|||
|
FILECNT DW 1 DUP(?)
|
|||
|
EXEFCB LABEL WORD
|
|||
|
IDLEN DB 1 DUP(?)
|
|||
|
ID DB 8 DUP(?)
|
|||
|
COM DB 3 DUP(?)
|
|||
|
DEST DB 37 DUP(?)
|
|||
|
DESTNAME DB 11 DUP(?)
|
|||
|
DIRBUF DB 37 DUP(?)
|
|||
|
BITS DW 1 DUP(?)
|
|||
|
FULLSCR DW 1 DUP(?)
|
|||
|
EXEEND DW 1 DUP(?)
|
|||
|
;Header variables for EXE file load
|
|||
|
;These are overlapped with COPY variables, below
|
|||
|
RUNVAR LABEL WORD
|
|||
|
RELPT DW 1 DUP(?)
|
|||
|
RELSEG DW 1 DUP(?)
|
|||
|
PSIZE LABEL WORD
|
|||
|
PAGES DW 1 DUP(?)
|
|||
|
RELCNT DW 1 DUP(?)
|
|||
|
HEADSIZ DW 1 DUP(?)
|
|||
|
DW 1 DUP(?)
|
|||
|
LOADLOW DW 1 DUP(?)
|
|||
|
INITSS DW 1 DUP(?)
|
|||
|
INITSP DW 1 DUP(?)
|
|||
|
DW 1 DUP(?)
|
|||
|
INITIP DW 1 DUP(?)
|
|||
|
INITCS DW 1 DUP(?)
|
|||
|
RELTAB DW 1 DUP(?)
|
|||
|
RUNVARSIZ EQU $-RUNVAR
|
|||
|
|
|||
|
DB 80H DUP(?)
|
|||
|
STACK LABEL WORD
|
|||
|
|
|||
|
PRETRLEN EQU $-ZERO ;Used later to compute TRNLEN
|
|||
|
|
|||
|
ORG RUNVAR-ZERO ;Overlaps EXE variables
|
|||
|
|
|||
|
SRCPT DW 1 DUP(?)
|
|||
|
INEXACT DB 1 DUP(?)
|
|||
|
APPEND DB 1 DUP(?)
|
|||
|
NOWRITE DB 1 DUP(?)
|
|||
|
ASCII DB 1 DUP(?)
|
|||
|
PLUS DB 1 DUP(?)
|
|||
|
SOURCE DB 11 DUP(?)
|
|||
|
TRANSPACESIZE EQU $-ZERO
|
|||
|
TRANSPACE ENDS
|
|||
|
|
|||
|
|
|||
|
;START OF RESIDENT PORTION
|
|||
|
|
|||
|
CODERES SEGMENT
|
|||
|
ASSUME CS:RESGROUP,DS:RESGROUP,ES:RESGROUP,SS:RESGROUP
|
|||
|
ORG 0
|
|||
|
ZERO = $
|
|||
|
PARMBUF LABEL WORD
|
|||
|
|
|||
|
ORG 100H
|
|||
|
|
|||
|
RSTACK LABEL WORD
|
|||
|
|
|||
|
PROGSTART:
|
|||
|
JMP CONPROC
|
|||
|
|
|||
|
LTPA DW 0 ;WILL STORE TPA SEGMENT HERE
|
|||
|
MYSEG DW 0 ;Put our own segment here
|
|||
|
|
|||
|
CONTC:
|
|||
|
MOV AX,CS
|
|||
|
MOV DS,AX
|
|||
|
MOV SS,AX
|
|||
|
MOV SP,OFFSET RESGROUP:RSTACK
|
|||
|
STI
|
|||
|
CALL SETVECT
|
|||
|
MOV AH,DSKRESET
|
|||
|
INT 33 ;Reset disks in case files were open
|
|||
|
TEST [BATCH],-1
|
|||
|
JZ LODCOM
|
|||
|
ASKEND:
|
|||
|
MOV DX,OFFSET RESGROUP:ENDBATMES
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 33
|
|||
|
MOV AX,0C00H+INCHAR
|
|||
|
INT 33
|
|||
|
AND AL,5FH
|
|||
|
CMP AL,"N"
|
|||
|
JZ LODCOM
|
|||
|
CMP AL,"Y"
|
|||
|
JNZ ASKEND
|
|||
|
MOV [BATCH],0
|
|||
|
LODCOM:
|
|||
|
MOV AX,CS
|
|||
|
MOV SS,AX
|
|||
|
MOV SP,OFFSET RESGROUP:RSTACK
|
|||
|
MOV DS,AX
|
|||
|
CALL SETVECT
|
|||
|
CALL CHKSUM
|
|||
|
CMP DX,[SUM]
|
|||
|
JZ HAVCOM
|
|||
|
MOV [LOADING],1
|
|||
|
CALL LOADCOM
|
|||
|
CHKSAME:
|
|||
|
CALL CHKSUM
|
|||
|
CMP DX,[SUM]
|
|||
|
JZ HAVCOM
|
|||
|
CALL WRONGCOM
|
|||
|
JMP SHORT CHKSAME
|
|||
|
HAVCOM:
|
|||
|
MOV [LOADING],0
|
|||
|
MOV SI,OFFSET RESGROUP:LTPA
|
|||
|
MOV DI,OFFSET TRANGROUP:TPA
|
|||
|
MOV ES,[TRNSEG]
|
|||
|
CLD
|
|||
|
MOVSW ;Move TPA segment to transient storage
|
|||
|
MOVSW ;Move resident segment too
|
|||
|
MOV AX,[MEMSIZ]
|
|||
|
MOV WORD PTR ES:[2],AX
|
|||
|
JMP DWORD PTR [TRANS]
|
|||
|
|
|||
|
RESIDENT:
|
|||
|
ADD DX,15
|
|||
|
MOV CL,4
|
|||
|
SHR DX,CL ;Number of paragraphs of new addition
|
|||
|
ADD CS:[LTPA],DX
|
|||
|
XOR AX,AX
|
|||
|
MOV DS,AX
|
|||
|
JMP DWORD PTR DS:[80H] ;Pretend user executed INT 20H
|
|||
|
|
|||
|
DSKERR:
|
|||
|
;******************************************************
|
|||
|
; THIS IS THE DEFAULT DISK ERROR HANDLING CODE
|
|||
|
; AVAILABLE TO ALL USERS IF THEY DO NOT TRY TO
|
|||
|
; INTERCEPT INTERRUPT 24H.
|
|||
|
;******************************************************
|
|||
|
STI
|
|||
|
PUSH DS
|
|||
|
PUSH CS
|
|||
|
POP DS ;Set up local data segment
|
|||
|
PUSH DX
|
|||
|
CALL CRLF
|
|||
|
POP DX
|
|||
|
ADD AL,"A" ;Compute drive letter
|
|||
|
MOV [DRVLET],AL
|
|||
|
TEST AH,80H ;Check if hard disk error
|
|||
|
JNZ FATERR
|
|||
|
MOV SI,OFFSET RESGROUP:READ
|
|||
|
TEST AH,1
|
|||
|
JZ SAVMES
|
|||
|
MOV SI,OFFSET RESGROUP:WRITE
|
|||
|
SAVMES:
|
|||
|
LODSW
|
|||
|
MOV WORD PTR [IOTYP],AX
|
|||
|
LODSW
|
|||
|
MOV WORD PTR [IOTYP+2],AX
|
|||
|
AND DI,0FFH
|
|||
|
CMP DI,12
|
|||
|
JBE HAVCOD
|
|||
|
MOV DI,12
|
|||
|
HAVCOD:
|
|||
|
MOV DI,WORD PTR [DI+MESBAS] ;Get pointer to error message
|
|||
|
XCHG DI,DX ;May need DX later
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 33 ;Print error type
|
|||
|
MOV DX,OFFSET RESGROUP:ERRMES
|
|||
|
INT 33
|
|||
|
CMP [LOADING],0
|
|||
|
JNZ GETCOMDSK
|
|||
|
ASK:
|
|||
|
MOV DX,OFFSET RESGROUP:REQUEST
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 33
|
|||
|
MOV AX,0C00H+INCHAR
|
|||
|
INT 33 ;Get response
|
|||
|
CALL CRLF
|
|||
|
OR AL,20H ;Convert to lower case
|
|||
|
MOV AH,0 ;Return code for ignore
|
|||
|
CMP AL,"i" ;Ignore?
|
|||
|
JZ EXIT
|
|||
|
INC AH
|
|||
|
CMP AL,"r" ;Retry?
|
|||
|
JZ EXIT
|
|||
|
INC AH
|
|||
|
CMP AL,"a" ;Abort?
|
|||
|
JNZ ASK
|
|||
|
EXIT:
|
|||
|
MOV AL,AH
|
|||
|
MOV DX,DI
|
|||
|
POP DS
|
|||
|
IRET
|
|||
|
|
|||
|
FATERR:
|
|||
|
MOV DX,OFFSET RESGROUP:BADFAT
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 33
|
|||
|
MOV DX,OFFSET RESGROUP:DRVNUM
|
|||
|
INT 33
|
|||
|
MOV AL,2 ;Abort
|
|||
|
POP DS
|
|||
|
IRET
|
|||
|
|
|||
|
GETCOMDSK:
|
|||
|
MOV DX,OFFSET RESGROUP:NEEDCOM
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 33
|
|||
|
MOV AX,0C07H ;Get char without testing or echo
|
|||
|
INT 33
|
|||
|
JMP LODCOM
|
|||
|
|
|||
|
CRLF:
|
|||
|
MOV DX,OFFSET RESGROUP:NEWLIN
|
|||
|
PUSH AX
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 33
|
|||
|
POP AX
|
|||
|
RET10: RET
|
|||
|
|
|||
|
LOADCOM:
|
|||
|
PUSH DS
|
|||
|
MOV DS,[TRNSEG]
|
|||
|
MOV DX,100H
|
|||
|
MOV AH,SETDMA
|
|||
|
INT 33
|
|||
|
POP DS
|
|||
|
MOV DX,OFFSET RESGROUP:COMFCB
|
|||
|
MOV AH,OPEN
|
|||
|
INT 33 ;Open COMMAND.COM
|
|||
|
OR AL,AL
|
|||
|
JZ READCOM
|
|||
|
MOV DX,OFFSET RESGROUP:NEEDCOM
|
|||
|
PROMPTCOM:
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 33
|
|||
|
MOV AX,0C07H ;Get char without testing or echo
|
|||
|
INT 33
|
|||
|
JMP SHORT LOADCOM
|
|||
|
READCOM:
|
|||
|
MOV WORD PTR[COMFCB+RR],OFFSET RESGROUP:TRANSTART
|
|||
|
XOR AX,AX
|
|||
|
MOV WORD PTR[COMFCB+RR+2],AX
|
|||
|
MOV [COMFCB],AL ;Use default drive
|
|||
|
INC AX
|
|||
|
MOV WORD PTR[COMFCB+RECLEN],AX
|
|||
|
MOV CX,COMLEN
|
|||
|
MOV DX,OFFSET RESGROUP:COMFCB
|
|||
|
MOV AH,RDBLK
|
|||
|
INT 33
|
|||
|
OR AL,AL
|
|||
|
JZ RET10
|
|||
|
WRONGCOM:
|
|||
|
MOV DX,OFFSET RESGROUP:COMBAD
|
|||
|
JMP SHORT PROMPTCOM
|
|||
|
|
|||
|
CHKSUM:
|
|||
|
CLD
|
|||
|
PUSH DS
|
|||
|
MOV DS,[TRNSEG]
|
|||
|
MOV SI,100H
|
|||
|
MOV CX,COMLEN
|
|||
|
SHR CX,1
|
|||
|
XOR DX,DX
|
|||
|
CHK:
|
|||
|
LODSW
|
|||
|
ADD DX,AX
|
|||
|
LOOP CHK
|
|||
|
POP DS
|
|||
|
RET
|
|||
|
|
|||
|
SETVECT:
|
|||
|
MOV DX,OFFSET RESGROUP:LODCOM
|
|||
|
MOV AX,2522H ;Set Terminate address
|
|||
|
INT 21H
|
|||
|
MOV DX,OFFSET RESGROUP:CONTC
|
|||
|
MOV AX,2523H ;Set Ctrl-C address
|
|||
|
INT 21H
|
|||
|
MOV DX,OFFSET RESGROUP:DSKERR
|
|||
|
MOV AX,2524H ;Set Hard Disk Error address
|
|||
|
INT 33
|
|||
|
MOV DX,OFFSET RESGROUP:RESIDENT
|
|||
|
MOV AX,2527H ;Set Terminate and Stay Resident address
|
|||
|
INT 33
|
|||
|
RET
|
|||
|
RESCODESIZE EQU $-ZERO
|
|||
|
CODERES ENDS
|
|||
|
|
|||
|
;*******************************************************************
|
|||
|
;START OF INIT PORTION
|
|||
|
;This code is overlayed the first time the TPA is used.
|
|||
|
|
|||
|
INIT SEGMENT BYTE
|
|||
|
|
|||
|
ORG 0
|
|||
|
ZERO = $
|
|||
|
CONPROC:
|
|||
|
MOV SP,OFFSET RESGROUP:RSTACK
|
|||
|
|
|||
|
IF HIGHMEM
|
|||
|
MOV AX,WORD PTR DS:[2]
|
|||
|
SUB AX,((RESCODESIZE+RESDATASIZE)+15)/16 ;Subtract size of resident
|
|||
|
MOV WORD PTR DS:[2],AX
|
|||
|
MOV ES,AX
|
|||
|
MOV SI,100H
|
|||
|
MOV DI,SI
|
|||
|
MOV CX,((RESCODESIZE+RESDATASIZE)-100H+1)/2 ;Length of resident in words
|
|||
|
REP MOVSW ;Move to end of memory
|
|||
|
MOV DS,AX
|
|||
|
MOV [LTPA],CS
|
|||
|
ENDIF
|
|||
|
|
|||
|
IF NOT HIGHMEM
|
|||
|
MOV AX,CS
|
|||
|
ADD AX,((RESCODESIZE+RESDATASIZE)+15)/16 ;Compute segment of TPA
|
|||
|
MOV [LTPA],AX
|
|||
|
MOV AX,WORD PTR DS:[2]
|
|||
|
ENDIF
|
|||
|
|
|||
|
MOV [MYSEG],DS
|
|||
|
MOV [MEMSIZ],AX
|
|||
|
SUB AX,TRNLEN ;Subtract size of transient
|
|||
|
MOV [TRNSEG],AX
|
|||
|
CALL SETVECT
|
|||
|
CALL LOADCOM
|
|||
|
CALL CHKSUM
|
|||
|
MOV [SUM],DX
|
|||
|
|
|||
|
IF MSVER
|
|||
|
IF HIGHMEM
|
|||
|
PUSH DS
|
|||
|
PUSH CS
|
|||
|
POP DS
|
|||
|
ENDIF
|
|||
|
MOV DX,OFFSET RESGROUP:HEADER
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 33
|
|||
|
IF HIGHMEM
|
|||
|
POP DS
|
|||
|
ENDIF
|
|||
|
ENDIF
|
|||
|
|
|||
|
MOV DX,OFFSET RESGROUP:BATFCB
|
|||
|
MOV AH,OPEN
|
|||
|
INT 33 ;See if AUTOEXEC.BAT exists
|
|||
|
MOV WORD PTR[BATFCB+RECLEN],1 ;Set record length to 1
|
|||
|
OR AL,AL ;Zero means file found
|
|||
|
JZ DRV0
|
|||
|
MOV [BATCH],0 ;Not found--turn off batch job
|
|||
|
MOV AX,OFFSET TRANGROUP:DATINIT
|
|||
|
MOV WORD PTR[INITADD],AX
|
|||
|
MOV AX,[TRNSEG]
|
|||
|
MOV WORD PTR[INITADD+2],AX
|
|||
|
CALL DWORD PTR DS:[INITADD]
|
|||
|
|
|||
|
IF IBMVER
|
|||
|
MOV DX,OFFSET RESGROUP:HEADER
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 33
|
|||
|
ENDIF
|
|||
|
|
|||
|
DRV0:
|
|||
|
JMP HAVCOM
|
|||
|
|
|||
|
|
|||
|
IF MSVER
|
|||
|
HEADER DB 13,10,"Command v. 1.17"
|
|||
|
IF HIGHMEM
|
|||
|
DB "H"
|
|||
|
ENDIF
|
|||
|
DB 13,10,"$"
|
|||
|
ENDIF
|
|||
|
|
|||
|
IF IBMVER
|
|||
|
HEADER DB 13,10,13,10,"The IBM Personal Computer DOS",13,10
|
|||
|
DB "Version 1.10 (C)Copyright IBM Corp 1981, 1982",13,10,"$"
|
|||
|
DB "Licensed Material - Program Property of IBM"
|
|||
|
ENDIF
|
|||
|
|
|||
|
INITSIZE EQU $-ZERO
|
|||
|
INIT ENDS
|
|||
|
|
|||
|
;This TAIL segment is used to produce a PARA aligned label in the resident
|
|||
|
; group which is the location where the transient segments will be loaded
|
|||
|
; initialy.
|
|||
|
|
|||
|
TAIL SEGMENT PARA
|
|||
|
ORG 0
|
|||
|
TRANSTART LABEL WORD
|
|||
|
TAIL ENDS
|
|||
|
|
|||
|
;********************************************************************
|
|||
|
;START OF TRANSIENT PORTION
|
|||
|
;This code is loaded at the end of memory and may be overwritten by
|
|||
|
;memory-intensive user programs.
|
|||
|
|
|||
|
TRANCODE SEGMENT PARA
|
|||
|
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:TRANGROUP
|
|||
|
|
|||
|
WSWITCH EQU 1 ;Wide display during DIR
|
|||
|
PSWITCH EQU 2 ;Pause (or Page) mode during DIR
|
|||
|
VSWITCH EQU 4 ;Verify during COPY
|
|||
|
ASWITCH EQU 8 ;ASCII mode during COPY
|
|||
|
BSWITCH EQU 10H ;Binary mode during COPY
|
|||
|
|
|||
|
ORG 0
|
|||
|
ZERO = $
|
|||
|
|
|||
|
ORG 100H ;Allow for 100H parameter area
|
|||
|
|
|||
|
SETDRV:
|
|||
|
MOV AH,SELDRV
|
|||
|
INT 21H
|
|||
|
COMMAND:
|
|||
|
CLD
|
|||
|
MOV AX,CS
|
|||
|
MOV SS,AX
|
|||
|
MOV SP,OFFSET TRANGROUP:STACK
|
|||
|
MOV ES,AX
|
|||
|
MOV DS,AX
|
|||
|
STI
|
|||
|
MOV AX,46*100H
|
|||
|
MOV DL,0
|
|||
|
INT 33 ;Turn off verify after write
|
|||
|
MOV AX,CS ;Get segment we're in
|
|||
|
SUB AX,[TPA] ;AX=size ot TPA in paragraphs
|
|||
|
MOV DX,16
|
|||
|
MUL DX ;DX:AX=size of TPA in bytes
|
|||
|
OR DX,DX ;See if over 64K
|
|||
|
JZ SAVSIZ ;OK if not
|
|||
|
MOV AX,-1 ;If so, limit to 65535 bytes
|
|||
|
SAVSIZ:
|
|||
|
MOV [BYTCNT],AX ;Max no. of bytes that can be buffered
|
|||
|
CALL CRLF2
|
|||
|
GETCOM:
|
|||
|
MOV AH,GETDRV
|
|||
|
INT 21H
|
|||
|
MOV [CURDRV],AL
|
|||
|
ADD AL,"A"
|
|||
|
CALL OUT ;Print letter for default drive
|
|||
|
MOV AL,SYM
|
|||
|
CALL OUT
|
|||
|
MOV DS,[RESSEG] ;All batch work must use resident seg.
|
|||
|
ASSUME DS:RESGROUP
|
|||
|
TEST [BATCH],-1
|
|||
|
JNZ READBAT
|
|||
|
PUSH CS
|
|||
|
POP DS ;Need local segment to point to buffer
|
|||
|
ASSUME DS:TRANGROUP
|
|||
|
MOV DX,OFFSET TRANGROUP:COMBUF
|
|||
|
MOV AH,INBUF
|
|||
|
INT 21H ;Get a command
|
|||
|
JMP DOCOM
|
|||
|
|
|||
|
;All batch proccessing has DS set to segment of resident portion
|
|||
|
ASSUME DS:RESGROUP
|
|||
|
NEEDPARM:
|
|||
|
CALL GETBATBYT
|
|||
|
CMP AL,"%" ;Check for two consecutive %
|
|||
|
JZ SAVBATBYT
|
|||
|
CMP AL,13 ;Check for end-of-line
|
|||
|
JZ SAVBATBYT
|
|||
|
SUB AL,"0"
|
|||
|
JB RDBAT ;Ignore parameter reference if invalid
|
|||
|
CMP AL,9
|
|||
|
JA RDBAT
|
|||
|
CBW
|
|||
|
MOV SI,AX
|
|||
|
SHL SI,1 ;Two bytes per entry
|
|||
|
MOV SI,[SI+OFFSET RESGROUP:PARMTAB] ;Get pointer to corresponding parameter
|
|||
|
CMP SI,-1 ;Check if parameter exists
|
|||
|
JZ RDBAT ;Ignore if it doesn't
|
|||
|
MOV AH,OUTCH
|
|||
|
RDPARM:
|
|||
|
LODSB ;From resident segment
|
|||
|
CMP AL,0DH ;Check for end of parameter
|
|||
|
JZ RDBAT
|
|||
|
STOSB ;To transient segment
|
|||
|
MOV DL,AL
|
|||
|
INT 33 ;Display paramters too
|
|||
|
JMP SHORT RDPARM
|
|||
|
|
|||
|
PROMPTBAT:
|
|||
|
MOV AH,PRINTBUF
|
|||
|
MOV DX,OFFSET RESGROUP:NEEDBAT
|
|||
|
INT 33 ;Prompt for batch file
|
|||
|
MOV AH,PRINTBUF
|
|||
|
MOV DX,OFFSET RESGROUP:PROMPT
|
|||
|
INT 33
|
|||
|
MOV AX,0C00H+INCHAR
|
|||
|
INT 33
|
|||
|
JMP COMMAND
|
|||
|
|
|||
|
BADCOMJ1:JMP BADCOM
|
|||
|
|
|||
|
READBAT:
|
|||
|
MOV DX,OFFSET RESGROUP:BATFCB
|
|||
|
MOV AH,OPEN
|
|||
|
INT 33 ;Make sure batch file still exists
|
|||
|
OR AL,AL
|
|||
|
JNZ PROMPTBAT ;If OPEN fails, prompt for disk
|
|||
|
MOV WORD PTR [BATFCB+RECLEN],1
|
|||
|
MOV DX,OFFSET RESGROUP:BATBYT
|
|||
|
MOV AH,SETDMA
|
|||
|
INT 33
|
|||
|
MOV DI,OFFSET TRANGROUP:COMBUF+2
|
|||
|
RDBAT:
|
|||
|
CALL GETBATBYT
|
|||
|
CMP AL,"%" ;Check for parameter
|
|||
|
JZ NEEDPARM
|
|||
|
SAVBATBYT:
|
|||
|
STOSB
|
|||
|
CALL OUT ;Display batched command line
|
|||
|
CMP AL,0DH
|
|||
|
JNZ RDBAT
|
|||
|
SUB DI,OFFSET TRANGROUP:COMBUF+3
|
|||
|
MOV AX,DI
|
|||
|
MOV ES:[COMBUF+1],AL ;Set length of line
|
|||
|
CALL GETBATBYT ;Eat linefeed
|
|||
|
PUSH CS
|
|||
|
POP DS ;Go back to local segment
|
|||
|
ASSUME DS:TRANGROUP
|
|||
|
DOCOM:
|
|||
|
;All segments are local for command line processing
|
|||
|
MOV AL,10
|
|||
|
CALL OUT
|
|||
|
MOV SI,OFFSET TRANGROUP:COMBUF+2
|
|||
|
MOV DI,OFFSET TRANGROUP:IDLEN
|
|||
|
MOV AX,2901H ;Make FCB with blank scan-off
|
|||
|
INT 21H
|
|||
|
CMP AL,1 ;Check for ambiguous command name
|
|||
|
JZ BADCOMJ1 ;Ambiguous commands not allowed
|
|||
|
CMP AL,-1
|
|||
|
JNZ DRVGD
|
|||
|
JMP DRVBAD
|
|||
|
DRVGD:
|
|||
|
MOV AL,[DI]
|
|||
|
MOV [SPECDRV],AL
|
|||
|
MOV AL," "
|
|||
|
MOV CX,9
|
|||
|
INC DI
|
|||
|
REPNE SCASB ;Count no. of letters in command name
|
|||
|
MOV AL,9
|
|||
|
SUB AL,CL
|
|||
|
MOV [IDLEN],AL
|
|||
|
MOV DI,81H
|
|||
|
MOV CX,0
|
|||
|
PUSH SI
|
|||
|
COMTAIL:
|
|||
|
LODSB
|
|||
|
STOSB ;Move command tail to 80H
|
|||
|
CMP AL,13
|
|||
|
LOOPNZ COMTAIL
|
|||
|
NOT CL
|
|||
|
MOV BYTE PTR DS:[80H],CL
|
|||
|
POP SI
|
|||
|
;If the command has 0 parameters must check here for
|
|||
|
;any switches that might be present.
|
|||
|
;SI -> first character after the command.
|
|||
|
MOV [FLAGER],0 ;Set error flag before any calls to switch
|
|||
|
CALL SWITCH ;Is the next character a "/"
|
|||
|
MOV [COMSW],AX
|
|||
|
MOV DI,FCB
|
|||
|
MOV AX,2901H
|
|||
|
INT 21H
|
|||
|
MOV [PARM1],AL ;Save result of parse
|
|||
|
CALL SWITCH
|
|||
|
MOV [ARG1S],AX
|
|||
|
MOV DI,FCB+10H
|
|||
|
MOV AX,2901H
|
|||
|
INT 21H ;Parse file name
|
|||
|
MOV [PARM2],AL ;Save result
|
|||
|
CALL SWITCH
|
|||
|
MOV [ARG2S],AX
|
|||
|
MOV AL,[IDLEN]
|
|||
|
MOV DL,[SPECDRV]
|
|||
|
OR DL,DL ;Check if drive was specified
|
|||
|
JZ OK
|
|||
|
JMP DRVCHK
|
|||
|
OK: DEC AL ;Check for null command
|
|||
|
JNZ FNDCOM
|
|||
|
JMP GETCOM
|
|||
|
|
|||
|
RETSW:
|
|||
|
XCHG AX,BX ;Put switches in AX
|
|||
|
RET
|
|||
|
|
|||
|
SWITCH:
|
|||
|
XOR BX,BX ;Initialize - no switches set
|
|||
|
SWLOOP:
|
|||
|
CALL SCANOFF ;Skip any delimiters
|
|||
|
CMP AL,"/" ;Is it a switch specifier?
|
|||
|
JNZ RETSW ;No -- we're finished
|
|||
|
INC SI ;Skip over "/"
|
|||
|
CALL SCANOFF
|
|||
|
INC SI
|
|||
|
;Convert lower case input to upper case
|
|||
|
CMP AL,"a"
|
|||
|
JB SAVCHR
|
|||
|
CMP AL,"z"
|
|||
|
JA SAVCHR
|
|||
|
SUB AL,20H ;Lower-case changed to upper-case
|
|||
|
SAVCHR:
|
|||
|
MOV DI,OFFSET TRANGROUP:SWLIST
|
|||
|
MOV CX,SWCOUNT
|
|||
|
REPNE SCASB ;Look for matching switch
|
|||
|
JNZ BADSW
|
|||
|
MOV AX,1
|
|||
|
SHL AX,CL ;Set a bit for the switch
|
|||
|
OR BX,AX
|
|||
|
JMP SHORT SWLOOP
|
|||
|
|
|||
|
BADSW:
|
|||
|
MOV [FLAGER],1 ;Record error in switch
|
|||
|
JMP SHORT SWLOOP
|
|||
|
|
|||
|
SWLIST DB "BAVPW"
|
|||
|
SWCOUNT EQU $-SWLIST
|
|||
|
|
|||
|
DRVBAD:
|
|||
|
MOV DX,OFFSET TRANGROUP:BADDRV
|
|||
|
JMP ERROR
|
|||
|
|
|||
|
FNDCOM:
|
|||
|
MOV SI,OFFSET TRANGROUP:COMTAB ;Prepare to search command table
|
|||
|
MOV CH,0
|
|||
|
FINDCOM:
|
|||
|
MOV DI,OFFSET TRANGROUP:IDLEN
|
|||
|
MOV CL,[SI]
|
|||
|
JCXZ EXTERNAL
|
|||
|
REPE CMPSB
|
|||
|
LAHF
|
|||
|
ADD SI,CX ;Bump to next position without affecting flags
|
|||
|
SAHF
|
|||
|
LODSB ;Get flag for drive check
|
|||
|
MOV [CHKDRV],AL
|
|||
|
LODSW ;Get address of command
|
|||
|
JNZ FINDCOM
|
|||
|
MOV DX,AX
|
|||
|
CMP [CHKDRV],0
|
|||
|
JZ NOCHECK
|
|||
|
MOV AL,[PARM1]
|
|||
|
OR AL,[PARM2] ;Check if either parm. had invalid drive
|
|||
|
CMP AL,-1
|
|||
|
JZ DRVBAD
|
|||
|
NOCHECK:CALL DX
|
|||
|
COMJMP: JMP COMMAND
|
|||
|
|
|||
|
BADCOMJ:JMP BADCOM
|
|||
|
|
|||
|
SETDRV1:
|
|||
|
JMP SETDRV
|
|||
|
|
|||
|
DRVCHK:
|
|||
|
DEC DL ;Adjust for correct drive number
|
|||
|
DEC AL ;Check if anything else is on line
|
|||
|
JZ SETDRV1
|
|||
|
EXTERNAL:
|
|||
|
MOV AL,[SPECDRV]
|
|||
|
MOV [IDLEN],AL
|
|||
|
MOV WORD PTR[COM],4F00H+"C" ;"CO"
|
|||
|
MOV BYTE PTR[COM+2],"M"
|
|||
|
MOV DX,OFFSET TRANGROUP:IDLEN
|
|||
|
MOV AH,OPEN
|
|||
|
INT 33 ;Check if command to be executed
|
|||
|
MOV [FILTYP],AL ;0 for COM files, -1 for EXE files
|
|||
|
OR AL,AL
|
|||
|
JZ EXECUTE
|
|||
|
MOV WORD PTR[COM],5800H+"E" ;"EX"
|
|||
|
MOV BYTE PTR[COM+2],"E"
|
|||
|
INT 33 ;Check for EXE file
|
|||
|
OR AL,AL
|
|||
|
JZ EXECUTE
|
|||
|
MOV WORD PTR[COM],4100H+"B" ;"BA"
|
|||
|
MOV BYTE PTR[COM+2],"T"
|
|||
|
INT 33 ;Check if batch file to be executed
|
|||
|
OR AL,AL
|
|||
|
JNZ BADCOMJ
|
|||
|
BATCOM:
|
|||
|
;Batch parameters are read with ES set to segment of resident part
|
|||
|
MOV ES,[RESSEG]
|
|||
|
ASSUME ES:RESGROUP
|
|||
|
MOV DI,OFFSET RESGROUP:PARMTAB
|
|||
|
MOV AX,-1
|
|||
|
MOV CX,10
|
|||
|
REP STOSW ;Zero parameter pointer table
|
|||
|
MOV SI,OFFSET TRANGROUP:COMBUF+2
|
|||
|
MOV DI,OFFSET RESGROUP:PARMBUF
|
|||
|
MOV BX,OFFSET RESGROUP:PARMTAB
|
|||
|
EACHPARM:
|
|||
|
CALL SCANOFF
|
|||
|
CMP AL,0DH
|
|||
|
JZ HAVPARM
|
|||
|
MOV ES:[BX],DI ;Set pointer table to point to actual parameter
|
|||
|
INC BX
|
|||
|
INC BX
|
|||
|
MOVPARM:
|
|||
|
LODSB
|
|||
|
CALL DELIM
|
|||
|
JZ ENDPARM ;Check for end of parameter
|
|||
|
STOSB
|
|||
|
CMP AL,0DH
|
|||
|
JZ HAVPARM
|
|||
|
JMP SHORT MOVPARM
|
|||
|
ENDPARM:
|
|||
|
MOV AL,0DH
|
|||
|
STOSB ;End-of-parameter marker
|
|||
|
CMP BX,OFFSET RESGROUP:PARMTAB+20 ;Maximum number of parameters?
|
|||
|
JB EACHPARM
|
|||
|
HAVPARM:
|
|||
|
MOV SI,OFFSET TRANGROUP:IDLEN
|
|||
|
MOV DI,OFFSET RESGROUP:BATFCB
|
|||
|
MOV CX,16
|
|||
|
REP MOVSW ;Move into private batch FCB
|
|||
|
XOR AX,AX
|
|||
|
PUSH ES
|
|||
|
POP DS ;Simply batch FCB setup
|
|||
|
ASSUME DS:RESGROUP
|
|||
|
MOV WORD PTR[BATFCB+RR],AX
|
|||
|
MOV WORD PTR[BATFCB+RR+2],AX ;Zero RR field
|
|||
|
INC AX
|
|||
|
MOV WORD PTR[BATFCB+RECLEN],AX ;Set record length to 1 byte
|
|||
|
MOV [BATCH],AL ;Flag batch job in progress
|
|||
|
JMP COMMAND
|
|||
|
ASSUME DS:TRANGROUP,ES:TRANGROUP
|
|||
|
|
|||
|
EXECUTE:
|
|||
|
MOV AX,WORD PTR[IDLEN+16]
|
|||
|
OR AX,WORD PTR[IDLEN+18] ;See if zero length
|
|||
|
JZ BADCOM ;If so, error
|
|||
|
XOR AX,AX
|
|||
|
MOV WORD PTR[IDLEN+RR],AX
|
|||
|
MOV WORD PTR[IDLEN+RR+2],AX ;Set RR field to zero
|
|||
|
INC AX
|
|||
|
MOV WORD PTR[IDLEN+RECLEN],AX ;Set record length field to 1
|
|||
|
MOV DX,[TPA]
|
|||
|
MOV BX,DX
|
|||
|
MOV AH,SETBASE
|
|||
|
INT 21H
|
|||
|
TEST [FILTYP],-1 ;Check if file is COM or EXE
|
|||
|
JZ COMLOAD
|
|||
|
JMP EXELOAD
|
|||
|
COMLOAD:PUSH DS
|
|||
|
MOV DS,DX
|
|||
|
MOV DX,100H
|
|||
|
MOV AH,SETDMA
|
|||
|
INT 21H
|
|||
|
POP DS
|
|||
|
MOV CX,[BYTCNT]
|
|||
|
SUB CX,100H
|
|||
|
MOV DX,OFFSET TRANGROUP:IDLEN
|
|||
|
MOV AH,RDBLK
|
|||
|
INT 21H
|
|||
|
DEC AL
|
|||
|
MOV DX,OFFSET TRANGROUP:TOOBIG
|
|||
|
JNZ ERROR
|
|||
|
;Set up exit conditions
|
|||
|
MOV CX,[BYTCNT]
|
|||
|
MOV DS,BX
|
|||
|
MOV ES,BX
|
|||
|
CLI
|
|||
|
MOV SS,BX
|
|||
|
MOV SP,CX
|
|||
|
STI
|
|||
|
SUB CX,100H ;Allow some stack space
|
|||
|
XOR AX,AX
|
|||
|
PUSH AX
|
|||
|
MOV AX,100H
|
|||
|
PUSH BX
|
|||
|
PUSH AX
|
|||
|
CALL SETUP
|
|||
|
XXX PROC FAR
|
|||
|
RET
|
|||
|
XXX ENDP
|
|||
|
BADCOM:
|
|||
|
MOV DX,OFFSET TRANGROUP:BADNAM
|
|||
|
ERROR:
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 21H
|
|||
|
JMP COMMAND
|
|||
|
|
|||
|
CHKCNT:
|
|||
|
TEST [FILECNT],-1
|
|||
|
JNZ ENDDIR
|
|||
|
MOV DX,OFFSET TRANGROUP:NOTFND
|
|||
|
JMP ERROR
|
|||
|
|
|||
|
ENDDIR:
|
|||
|
;Make sure last line ends with CR/LF
|
|||
|
MOV AL,[LINLEN]
|
|||
|
CMP AL,[LINCNT] ;Will be equal if just had CR/LF
|
|||
|
JZ MESSAGE
|
|||
|
CALL CRLF2
|
|||
|
MESSAGE:
|
|||
|
MOV SI,[FILECNT]
|
|||
|
XOR DI,DI
|
|||
|
CALL DISP32BITS
|
|||
|
MOV DX,OFFSET TRANGROUP:DIRMES
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 21H
|
|||
|
RET
|
|||
|
|
|||
|
CATALOG:
|
|||
|
MOV AL,"?" ;*.* is default file spec.
|
|||
|
MOV DI,5DH
|
|||
|
MOV CX,11
|
|||
|
REP STOSB
|
|||
|
MOV SI,81H
|
|||
|
CALL SWITCH
|
|||
|
MOV DI,5CH
|
|||
|
MOV AX,41*100H+0DH ;Parse with default name and extension
|
|||
|
INT 33
|
|||
|
|
|||
|
;Begin by processing any switches that may have been specified.
|
|||
|
;BITS will contain any information about switches that was
|
|||
|
;found when the command line was parsed.
|
|||
|
|
|||
|
SETSWT:
|
|||
|
MOV AX,[COMSW] ;Get switches from command
|
|||
|
OR AX,[ARG1S] ;OR in switches from first parameter
|
|||
|
MOV [BITS],AX
|
|||
|
MOV BYTE PTR[FULLSCR],LINPERPAG
|
|||
|
TEST AL,1 ;Look for /W
|
|||
|
MOV AL,NORMPERLIN
|
|||
|
JZ DIR
|
|||
|
MOV AL,WIDEPERLIN
|
|||
|
DIR:
|
|||
|
MOV [LINLEN],AL ;Set number of entries per line
|
|||
|
MOV [LINCNT],AL
|
|||
|
MOV [FILECNT],0 ;Keep track of how many files found
|
|||
|
MOV DX,OFFSET TRANGROUP:DIRBUF ;Set Disk transfer address
|
|||
|
MOV AH,SETDMA
|
|||
|
INT 21H
|
|||
|
MOV AH,SRCHFRST
|
|||
|
SHOWDIR:
|
|||
|
MOV DX,5CH ;DX -> Unopened FCB
|
|||
|
INT 21H ;Search for a file to match FCB
|
|||
|
INC AL ;FF = file not found
|
|||
|
JNZ AGAIN ;Either an error or we are finished
|
|||
|
JMP CHKCNT
|
|||
|
AGAIN:
|
|||
|
INC [FILECNT] ;Keep track of how many we find
|
|||
|
MOV SI,OFFSET TRANGROUP:DIRBUF+1 ;SI -> information returned by sys call
|
|||
|
CALL SHONAME
|
|||
|
TEST BYTE PTR[BITS],1 ;/W set?
|
|||
|
JNZ NEXENT ;If so, no size, date, or time
|
|||
|
CALL DISPSIZE ;Print size of file
|
|||
|
CALL TWOSPC
|
|||
|
MOV AX,WORD PTR[DIRBUF+25] ;Get date
|
|||
|
OR AX,AX
|
|||
|
JZ NEXENT ;Skip if no date
|
|||
|
MOV DX,AX
|
|||
|
MOV CL,5
|
|||
|
SHR AX,CL ;Align month
|
|||
|
AND AL,0FH
|
|||
|
MOV BH,"0"-" " ;Enable zero suppression
|
|||
|
CALL OUT2
|
|||
|
MOV AL,"-"
|
|||
|
CALL OUT
|
|||
|
MOV AL,DL
|
|||
|
AND AL,1FH ;Mask to day
|
|||
|
CALL OUT2
|
|||
|
MOV AL,"-"
|
|||
|
CALL OUT
|
|||
|
MOV AL,DH
|
|||
|
SHR AL,1 ;Align year
|
|||
|
ADD AX,80 ;Relative 1980
|
|||
|
CMP AL,100
|
|||
|
JB MILLENIUM
|
|||
|
SUB AL,100
|
|||
|
MILLENIUM:
|
|||
|
CALL OUT2
|
|||
|
MOV BX,WORD PTR[DIRBUF+23] ;Get time
|
|||
|
OR BX,BX ;Time field present?
|
|||
|
JZ NEXENT
|
|||
|
CALL TWOSPC
|
|||
|
SHR BX,1
|
|||
|
SHR BX,1
|
|||
|
SHR BX,1
|
|||
|
SHR BL,1
|
|||
|
SHR BL,1 ;Hours in BH, minutes in BL
|
|||
|
MOV AL,BH
|
|||
|
MOV DH,"a" ;Assume A.M.
|
|||
|
CMP AL,12 ;In the afternoon?
|
|||
|
JB MORN
|
|||
|
MOV DH,"p"
|
|||
|
JE MORN
|
|||
|
SUB AL,12 ;Keep it to 12 hours or less
|
|||
|
MORN:
|
|||
|
OR AL,AL ;Before 1 am?
|
|||
|
JNZ SHOHOURS
|
|||
|
MOV AL,12
|
|||
|
SHOHOURS:
|
|||
|
MOV BH,"0"-" " ;Enable zero suppression
|
|||
|
CALL OUT2
|
|||
|
MOV AL,":"
|
|||
|
CALL OUT
|
|||
|
MOV AL,BL ;Output minutes
|
|||
|
CALL OUT2
|
|||
|
MOV AL,DH ;Get "a" or "p"
|
|||
|
CALL OUT
|
|||
|
NEXENT:
|
|||
|
DEC [LINCNT]
|
|||
|
JNZ SAMLIN
|
|||
|
NEXLIN:
|
|||
|
MOV AL,[LINLEN]
|
|||
|
MOV [LINCNT],AL
|
|||
|
CALL CRLF2
|
|||
|
TEST BYTE PTR[BITS],2 ;/P switch present?
|
|||
|
JZ SCROLL ;If not, just continue
|
|||
|
DEC BYTE PTR[FULLSCR]
|
|||
|
JNZ SCROLL
|
|||
|
MOV BYTE PTR[FULLSCR],LINPERPAG
|
|||
|
MOV AH,PRINTBUF
|
|||
|
MOV DX,OFFSET TRANGROUP:PAUSMES
|
|||
|
INT 33
|
|||
|
MOV AX,0C08H ;Wait for any character to be typed
|
|||
|
INT 21H
|
|||
|
CALL CRLF2
|
|||
|
SCROLL:
|
|||
|
MOV AH,SRCHNXT
|
|||
|
JMP SHOWDIR
|
|||
|
|
|||
|
SAMLIN:
|
|||
|
MOV AL,9 ;Output a tab
|
|||
|
CALL OUT
|
|||
|
JMP SHORT SCROLL
|
|||
|
|
|||
|
SHONAME:
|
|||
|
MOV CX,8
|
|||
|
CALL OUTCNT
|
|||
|
CALL ONESPC
|
|||
|
MOV CX,3
|
|||
|
OUTCNT:
|
|||
|
LODSB
|
|||
|
CALL OUT
|
|||
|
LOOP OUTCNT
|
|||
|
RET
|
|||
|
|
|||
|
TWOSPC:
|
|||
|
CALL ONESPC
|
|||
|
ONESPC:
|
|||
|
MOV AL," "
|
|||
|
JMP OUT
|
|||
|
|
|||
|
CRLF2:
|
|||
|
MOV AL,13
|
|||
|
CALL OUT
|
|||
|
MOV AL,10
|
|||
|
JMP OUT
|
|||
|
|
|||
|
DISPSIZE:
|
|||
|
MOV SI,WORD PTR[DIRBUF+29]
|
|||
|
MOV DI,WORD PTR[DIRBUF+31]
|
|||
|
DISP32BITS:
|
|||
|
;Prints the 32-bit number DI:SI on the console in decimal. Uses a total
|
|||
|
;of 9 digit positions with leading blanks.
|
|||
|
XOR AX,AX
|
|||
|
MOV BX,AX
|
|||
|
MOV BP,AX
|
|||
|
MOV CX,32
|
|||
|
CONVLP:
|
|||
|
SHL SI,1
|
|||
|
RCL DI,1
|
|||
|
XCHG AX,BP
|
|||
|
CALL CONVWRD
|
|||
|
XCHG AX,BP
|
|||
|
XCHG AX,BX
|
|||
|
CALL CONVWRD
|
|||
|
XCHG AX,BX
|
|||
|
ADC AL,0
|
|||
|
LOOP CONVLP
|
|||
|
; Conversion complete. Print 9-digit number.
|
|||
|
MOV CX,1810H ;Allow leading zero blanking for 8 digits
|
|||
|
XCHG DX,AX
|
|||
|
CALL DIGIT
|
|||
|
XCHG AX,BX
|
|||
|
CALL OUTWORD
|
|||
|
XCHG AX,BP
|
|||
|
OUTWORD:
|
|||
|
PUSH AX
|
|||
|
MOV DL,AH
|
|||
|
CALL OUTBYTE
|
|||
|
POP DX
|
|||
|
OUTBYTE:
|
|||
|
MOV DH,DL
|
|||
|
SHR DL,1
|
|||
|
SHR DL,1
|
|||
|
SHR DL,1
|
|||
|
SHR DL,1
|
|||
|
CALL DIGIT
|
|||
|
MOV DL,DH
|
|||
|
DIGIT:
|
|||
|
AND DL,0FH
|
|||
|
JZ BLANKZER
|
|||
|
MOV CL,0
|
|||
|
BLANKZER:
|
|||
|
DEC CH
|
|||
|
AND CL,CH
|
|||
|
OR DL,30H
|
|||
|
SUB DL,CL
|
|||
|
MOV AH,OUTCH
|
|||
|
INT 21H
|
|||
|
RET
|
|||
|
|
|||
|
CONVWRD:
|
|||
|
ADC AL,AL
|
|||
|
DAA
|
|||
|
XCHG AL,AH
|
|||
|
ADC AL,AL
|
|||
|
DAA
|
|||
|
XCHG AL,AH
|
|||
|
RET20: RET
|
|||
|
|
|||
|
ERASE:
|
|||
|
MOV CX,11
|
|||
|
MOV SI,FCB+1
|
|||
|
AMBSPEC:
|
|||
|
LODSB
|
|||
|
CMP AL,"?"
|
|||
|
JNZ ALLFIL
|
|||
|
LOOP AMBSPEC
|
|||
|
ALLFIL:
|
|||
|
CMP CX,0
|
|||
|
JNZ NOPRMPT
|
|||
|
ASKAGN:
|
|||
|
MOV DX,OFFSET TRANGROUP:SUREMES ;"Are you sure (Y/N)?"
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 21H
|
|||
|
MOV AX,0C00H+INCHAR
|
|||
|
INT 21H
|
|||
|
AND AL,5FH
|
|||
|
CMP AL,"N"
|
|||
|
JZ RET20
|
|||
|
CMP AL,"Y"
|
|||
|
CALL CRLF2
|
|||
|
JZ NOPRMPT
|
|||
|
JMP SHORT ASKAGN
|
|||
|
NOPRMPT:
|
|||
|
MOV AH,DELETE
|
|||
|
MOV BX,OFFSET TRANGROUP:NOTFND
|
|||
|
CMP BYTE PTR DS:[FCB+1]," " ;Check if parameter exists
|
|||
|
JMP SHORT OPFILE
|
|||
|
RENAME:
|
|||
|
MOV AH,RENAM
|
|||
|
MOV BX,OFFSET TRANGROUP:RENERR
|
|||
|
CMP BYTE PTR DS:[FCB+16+1]," " ;Check if parameter exists
|
|||
|
OPFILE:
|
|||
|
MOV DX,OFFSET TRANGROUP:MISNAM
|
|||
|
JZ ERRJ ;Error if missing parameter
|
|||
|
MOV DX,FCB
|
|||
|
INT 21H
|
|||
|
INC AL
|
|||
|
JNZ RET20
|
|||
|
MOV DX,BX
|
|||
|
ERRJ: JMP ERROR
|
|||
|
|
|||
|
TYPEFIL:
|
|||
|
MOV DS,[TPA]
|
|||
|
XOR DX,DX
|
|||
|
MOV AH,SETDMA
|
|||
|
INT 21H
|
|||
|
PUSH CS
|
|||
|
POP DS
|
|||
|
MOV DX,FCB
|
|||
|
MOV AH,OPEN
|
|||
|
INT 21H
|
|||
|
OR AL,AL
|
|||
|
MOV DX,OFFSET TRANGROUP:NOTFND
|
|||
|
JNZ ERRJ
|
|||
|
XOR AX,AX
|
|||
|
MOV WORD PTR DS:[FCB+RR],AX ;Set RR field
|
|||
|
MOV WORD PTR DS:[FCB+RR+2],AX
|
|||
|
INC AX
|
|||
|
MOV WORD PTR DS:[FCB+RECLEN],AX ;Set record length
|
|||
|
MOV ES,[TPA]
|
|||
|
TYPELP:
|
|||
|
MOV DX,FCB
|
|||
|
MOV CX,[BYTCNT]
|
|||
|
MOV AH,RDBLK
|
|||
|
INT 21H
|
|||
|
JCXZ RET30
|
|||
|
XOR SI,SI ;Start at 0 in TPA
|
|||
|
OUTLP:
|
|||
|
LODS BYTE PTR ES:[SI] ;In TPA segment
|
|||
|
CMP AL,1AH
|
|||
|
JZ RET30
|
|||
|
MOV AH,OUTCH
|
|||
|
MOV DL,AL
|
|||
|
INT 21H
|
|||
|
LOOP OUTLP
|
|||
|
JMP SHORT TYPELP
|
|||
|
|
|||
|
RET30: RET ;Need a nearby RET
|
|||
|
|
|||
|
COPY:
|
|||
|
XOR AX,AX
|
|||
|
MOV [PLUS],AL ;Will keep track of "+"s
|
|||
|
MOV [FILECNT],AX
|
|||
|
MOV SI,81H ;Point to input line
|
|||
|
CALL SWITCH ;Skip over switches on command
|
|||
|
MOV BP,AX
|
|||
|
MOV DI,FCB
|
|||
|
CALL PARSNAM ;Scan first source
|
|||
|
MOV [PARM1],DL ;Save ambiguous flag
|
|||
|
MOV [SRCPT],SI ;Save pointer to command line
|
|||
|
;Parse each name to find destination and check for /V switch
|
|||
|
SCANNAM:
|
|||
|
CALL PARSE
|
|||
|
JNZ SCANNAM
|
|||
|
GETDEST:
|
|||
|
MOV DI,OFFSET TRANGROUP:DEST
|
|||
|
MOV BX,BP ;Remeber switches so far
|
|||
|
XOR BP,BP ;Must have dest. swtiches alone
|
|||
|
CALL PARSNAM
|
|||
|
MOV [ARG2S],BP ;Remember switches on destination
|
|||
|
JNZ HAVDESTNAM ;File name present?
|
|||
|
INC DI ;Point to file name spot
|
|||
|
MOV AL,"?" ;Substitute *.*
|
|||
|
MOV CX,11
|
|||
|
REP STOSB
|
|||
|
HAVDESTNAM:
|
|||
|
OR BX,BP ;BX = all switches combined
|
|||
|
AND BL,VSWITCH ;Verify requested?
|
|||
|
JZ NOVER
|
|||
|
MOV AX,46*100H+1 ;Set verify
|
|||
|
MOV DL,0
|
|||
|
INT 33
|
|||
|
NOVER:
|
|||
|
MOV DI,OFFSET TRANGROUP:DESTNAME
|
|||
|
MOV SI,OFFSET TRANGROUP:DEST+1
|
|||
|
MOV BX,FCB+1
|
|||
|
CALL BUILDNAME ;See if we can make it unambiguous
|
|||
|
MOV DI,OFFSET TRANGROUP:DESTNAME
|
|||
|
MOV AL,"?"
|
|||
|
MOV CX,11
|
|||
|
REPNE SCASB ;Scan for "?" to see if ambiguous
|
|||
|
MOV AL,1 ;Flag if ambig.
|
|||
|
JZ AMBIG
|
|||
|
DEC AX ;AL=0 if unambig.
|
|||
|
AMBIG:
|
|||
|
MOV DL,AL
|
|||
|
MOV AH,[PLUS] ;1=found "+"
|
|||
|
XOR AL,1 ;0=ambig, 1=unambig destination
|
|||
|
AND AL,[PARM1] ;Source ambig. AND dest unambig.
|
|||
|
OR AL,AH ;OR found "+" means concatenation
|
|||
|
MOV [ASCII],AL ;Concatenation implies ASCII mode
|
|||
|
MOV [INEXACT],AL ;ASCII implies inexact copy
|
|||
|
SHL AL,1
|
|||
|
OR AL,DL ;Combine multiple and concat flags
|
|||
|
MOV [PARM2],AL
|
|||
|
MOV AL,BYTE PTR[COMSW]
|
|||
|
CALL SETASC ;Check /A,/B on command
|
|||
|
MOV AL,BYTE PTR[ARG1S]
|
|||
|
CALL SETASC ;Check for ASCII on first filename
|
|||
|
MOV BYTE PTR[COMSW],AL ;Save starting switch values
|
|||
|
MOV AH,SRCHFRST
|
|||
|
CALL SEARCH ;Search for first source name
|
|||
|
MULTDEST:
|
|||
|
JZ FIRSTSRC ;Find a first source name?
|
|||
|
TEST [PARM2],1 ;If multiple, we're done
|
|||
|
JNZ ENDCOPY
|
|||
|
XOR AX,AX
|
|||
|
MOV [NXTADD],AX
|
|||
|
MOV [CFLAG],AL ;Flag nothing read yet
|
|||
|
NEXTSNG:
|
|||
|
MOV DI,FCB
|
|||
|
MOV SI,[SRCPT]
|
|||
|
CALL PARSESRC ;Parse next file name into FCB
|
|||
|
MOV [PARM1],DL ;Remember if it's ambiguous
|
|||
|
MOV [SRCPT],SI
|
|||
|
JZ SNGCLOS
|
|||
|
MOV AH,SRCHFRST
|
|||
|
CALL SEARCH ;Search for new file name
|
|||
|
JNZ NEXTSNG ;If none, skip it and move to next name
|
|||
|
READSNG:
|
|||
|
CALL CHECKREAD
|
|||
|
SNGLOOP:
|
|||
|
CALL SEARCHNEXT ;See if any more of this name
|
|||
|
JZ READSNG
|
|||
|
JMP SHORT NEXTSNG
|
|||
|
|
|||
|
SNGCLOS:
|
|||
|
CALL CLOSEFIL
|
|||
|
ENDCOPY:
|
|||
|
MOV SI,[FILECNT]
|
|||
|
XOR DI,DI
|
|||
|
CALL DISP32BITS
|
|||
|
MOV DX,OFFSET TRANGROUP:COPIED
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 21H
|
|||
|
JMP COMMAND ;Stack could be messed up
|
|||
|
|
|||
|
FIRSTSRC:
|
|||
|
MOV SI,OFFSET TRANGROUP:DIRBUF+1
|
|||
|
MOV DI,OFFSET TRANGROUP:SOURCE
|
|||
|
MOV CX,11
|
|||
|
REP MOVSB ;Copy first source name to SOURCE
|
|||
|
MOV SI,OFFSET TRANGROUP:DESTNAME
|
|||
|
MOV DI,OFFSET TRANGROUP:DEST+1
|
|||
|
MOV BX,OFFSET TRANGROUP:SOURCE
|
|||
|
CALL BUILDNAME ;Build destination name
|
|||
|
XOR AX,AX
|
|||
|
MOV [NXTADD],AX
|
|||
|
MOV [CFLAG],AL
|
|||
|
MOV [APPEND],AL
|
|||
|
MOV [NOWRITE],AL
|
|||
|
TEST [PARM2],1 ;Multiple destinations?
|
|||
|
JZ NOPRT
|
|||
|
MOV SI,OFFSET TRANGROUP:DIRBUF+1
|
|||
|
CALL SHONAME ;If so, show first source
|
|||
|
CALL CRLF2
|
|||
|
NOPRT:
|
|||
|
CALL COMPNAME ;Source and dest. the same?
|
|||
|
JNZ DOREAD ;If not, read source in
|
|||
|
TEST [PARM2],2 ;Concatenation?
|
|||
|
MOV DX,OFFSET TRANGROUP:OVERWR
|
|||
|
JZ COPERRJ ;If not, overwrite error
|
|||
|
MOV [APPEND],1 ;Set physical append
|
|||
|
MOV AH,OPEN
|
|||
|
MOV DX,OFFSET TRANGROUP:DEST
|
|||
|
INT 33 ;Open (existing) destination
|
|||
|
CMP [ASCII],0 ;ASCII flag set?
|
|||
|
JZ BINARYAPP
|
|||
|
;ASCII append. Must find logical EOF, then seek there with dest. FCB
|
|||
|
MOV [NOWRITE],1
|
|||
|
CALL READIN ;Find EOF
|
|||
|
CALL FLSHFIL ;Seek there
|
|||
|
MOV [NOWRITE],0
|
|||
|
CALL FLSHFIL ;Truncate file
|
|||
|
JMP SHORT SNGLCHK
|
|||
|
|
|||
|
SNGLOOPJ:JMP SNGLOOP
|
|||
|
|
|||
|
COPERRJ:JMP COPERR
|
|||
|
|
|||
|
BINARYAPP:
|
|||
|
MOV WORD PTR[DEST+RECLEN],1 ;Set record length to 1
|
|||
|
MOV SI,OFFSET TRANGROUP:DEST+16 ;Point to file size
|
|||
|
MOV DI,OFFSET TRANGROUP:DEST+RR
|
|||
|
MOVSW
|
|||
|
MOVSW ;Seek to end of file
|
|||
|
MOV [CFLAG],1
|
|||
|
JMP SHORT SNGLCHK
|
|||
|
DOREAD:
|
|||
|
CALL READIN
|
|||
|
SNGLCHK:
|
|||
|
TEST [PARM2],1 ;Single or multiple destinations?
|
|||
|
JZ SNGLOOPJ
|
|||
|
MOV SI,[SRCPT]
|
|||
|
MULTAPP:
|
|||
|
CALL PARSE
|
|||
|
JZ MULTCLOS
|
|||
|
PUSH SI
|
|||
|
MOV SI,OFFSET TRANGROUP:DIRBUF+1
|
|||
|
MOV DI,SI
|
|||
|
MOV BX,OFFSET TRANGROUP:SOURCE
|
|||
|
CALL BUILDNAME
|
|||
|
CALL CHECKREAD
|
|||
|
POP SI
|
|||
|
JMP SHORT MULTAPP
|
|||
|
MULTCLOS:
|
|||
|
CALL CLOSEFIL
|
|||
|
MOV AL,BYTE PTR[COMSW]
|
|||
|
MOV [ASCII],AL ;Restore ASCII flag
|
|||
|
CALL SEARCHNEXT
|
|||
|
JMP MULTDEST
|
|||
|
|
|||
|
PARSE:
|
|||
|
MOV DI,OFFSET TRANGROUP:DIRBUF
|
|||
|
PARSESRC:
|
|||
|
CALL SCANOFF
|
|||
|
CMP AL,"+"
|
|||
|
JNZ RETZF
|
|||
|
MOV [PLUS],1 ;Keep track of "+" signs
|
|||
|
INC SI ;Skip over it
|
|||
|
PARSNAM:
|
|||
|
MOV AX,2901H
|
|||
|
INT 33 ;Parse file name
|
|||
|
CMP AL,-1 ;Illegal?
|
|||
|
MOV DX,OFFSET TRANGROUP:BADDRV
|
|||
|
JZ COPERRJ
|
|||
|
XCHG AX,DX ;Save parse flag in DL
|
|||
|
MOV AL,BYTE PTR[DI] ;Get drive number
|
|||
|
OR AL,AL ;Is it default?
|
|||
|
JNZ PARSW
|
|||
|
MOV AL,[CURDRV] ;Substitute actual drive
|
|||
|
INC AX
|
|||
|
MOV BYTE PTR[DI],AL
|
|||
|
PARSW:
|
|||
|
PUSH BX
|
|||
|
PUSH DI
|
|||
|
CALL SWITCH ;Process switches
|
|||
|
OR BP,AX ;Combine all switches
|
|||
|
CALL SETASC ;Check for /A or /B
|
|||
|
POP DI
|
|||
|
POP BX
|
|||
|
CMP BYTE PTR[DI+1]," " ;Did we even get a file name?
|
|||
|
RET
|
|||
|
|
|||
|
RETZF:
|
|||
|
XOR AX,AX
|
|||
|
RET35: RET
|
|||
|
|
|||
|
SEARCHNEXT:
|
|||
|
MOV AL,[PARM1] ;Is name ambiguous?
|
|||
|
DEC AL
|
|||
|
JNZ RET35 ;Don't perform search if not
|
|||
|
MOV AH,SRCHNXT
|
|||
|
SEARCH:
|
|||
|
PUSH AX
|
|||
|
MOV AH,SETDMA
|
|||
|
MOV DX,OFFSET TRANGROUP:DIRBUF
|
|||
|
INT 33 ;Put result of search in DIRBUF
|
|||
|
POP AX ;Restore search first/next command
|
|||
|
MOV DX,FCB
|
|||
|
INT 33 ;Do the search
|
|||
|
OR AL,AL
|
|||
|
RET
|
|||
|
|
|||
|
SETASC:
|
|||
|
;Given switch vector in AX,
|
|||
|
; Set ASCII switch if /A is set
|
|||
|
; Clear ASCII switch if /B is set
|
|||
|
; Leave ASCII unchanged if neither or both are set
|
|||
|
; Also sets INEXACT if ASCII is ever set. AL = ASCII on exit, flags set
|
|||
|
AND AL,ASWITCH+BSWITCH
|
|||
|
JPE LOADSW ;PE means both or neither are set
|
|||
|
AND AL,ASWITCH
|
|||
|
MOV [ASCII],AL
|
|||
|
OR [INEXACT],AL
|
|||
|
LOADSW:
|
|||
|
MOV AL,[ASCII]
|
|||
|
OR AL,AL
|
|||
|
RET
|
|||
|
|
|||
|
BUILDNAME:
|
|||
|
; [SI] = Ambiguous input file name
|
|||
|
; [BX] = Source of replacement characters
|
|||
|
; [DI] = Destination
|
|||
|
; File name is copied from [SI] to [DI]. If "?"s are encountered,
|
|||
|
; they are replaced with the character in the same position at [BX].
|
|||
|
MOV CX,11
|
|||
|
BUILDNAM:
|
|||
|
LODSB
|
|||
|
CMP AL,"?"
|
|||
|
JNZ NOTAMBIG
|
|||
|
MOV AL,BYTE PTR[BX]
|
|||
|
NOTAMBIG:
|
|||
|
STOSB
|
|||
|
INC BX
|
|||
|
LOOP BUILDNAM
|
|||
|
RET
|
|||
|
|
|||
|
COMPNAME:
|
|||
|
MOV SI,OFFSET TRANGROUP:DEST
|
|||
|
MOV DI,OFFSET TRANGROUP:DIRBUF
|
|||
|
MOV CX,6
|
|||
|
REPE CMPSW
|
|||
|
RET
|
|||
|
|
|||
|
CHECKREAD:
|
|||
|
;Read file in (with READIN) if not identical to destination
|
|||
|
CALL COMPNAME ;See if source and destination the same
|
|||
|
JNZ READIN
|
|||
|
CMP [APPEND],0 ;If physical append, it's OK
|
|||
|
JNZ RET40
|
|||
|
MOV DX,OFFSET TRANGROUP:LOSTERR ;Tell him he's not going to get it
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 33
|
|||
|
RET40: RET
|
|||
|
|
|||
|
READIN:
|
|||
|
;Open source file and read it in. If memory fills up, flush it out to
|
|||
|
;destination and keep reading. If /A switch set, chop file at first ^Z.
|
|||
|
; Inputs/Outputs:
|
|||
|
; [NXTADD] has current pointer in buffer
|
|||
|
; [CFLAG] <>0 if destination has been created
|
|||
|
|
|||
|
MOV DX,OFFSET TRANGROUP:DIRBUF
|
|||
|
MOV AH,OPEN
|
|||
|
INT 21H
|
|||
|
OR AL,AL ;Successful open?
|
|||
|
JNZ RET40 ;If not, just ignore it
|
|||
|
XOR AX,AX
|
|||
|
MOV WORD PTR[DIRBUF+RR],AX
|
|||
|
MOV WORD PTR[DIRBUF+RR+2],AX
|
|||
|
INC AX
|
|||
|
MOV WORD PTR[DIRBUF+RECLEN],AX
|
|||
|
COPYLP:
|
|||
|
MOV DX,[NXTADD]
|
|||
|
MOV AH,SETDMA
|
|||
|
PUSH DS
|
|||
|
MOV DS,[TPA]
|
|||
|
INT 33
|
|||
|
POP DS
|
|||
|
MOV CX,[BYTCNT]
|
|||
|
SUB CX,DX ;Compute available space
|
|||
|
MOV DX,OFFSET TRANGROUP:DIRBUF
|
|||
|
MOV AH,RDBLK ;Read in source file
|
|||
|
INT 21H
|
|||
|
JCXZ RET40
|
|||
|
CMP [ASCII],0
|
|||
|
JZ BINREAD
|
|||
|
MOV DX,CX
|
|||
|
MOV DI,[NXTADD]
|
|||
|
MOV AL,1AH
|
|||
|
PUSH ES
|
|||
|
MOV ES,[TPA]
|
|||
|
REPNE SCASB ;Scan for EOF
|
|||
|
POP ES
|
|||
|
JNZ USEALL
|
|||
|
INC CX
|
|||
|
USEALL:
|
|||
|
SUB DX,CX
|
|||
|
MOV CX,DX
|
|||
|
BINREAD:
|
|||
|
ADD CX,[NXTADD]
|
|||
|
MOV [NXTADD],CX
|
|||
|
CMP CX,[BYTCNT] ;Is buffer full?
|
|||
|
JB RET40 ;If not, we must have found EOF
|
|||
|
CALL FLSHFIL
|
|||
|
JMP SHORT COPYLP
|
|||
|
|
|||
|
CLOSEFIL:
|
|||
|
MOV AX,[NXTADD]
|
|||
|
MOV BX,AX
|
|||
|
OR AL,AH ;See if any data is loaded
|
|||
|
OR AL,[CFLAG] ; or file was created
|
|||
|
JZ RET50 ;Don't close or count if not created
|
|||
|
MOV AL,BYTE PTR[ARG2S]
|
|||
|
CALL SETASC ;Check for /B or /A on destination
|
|||
|
JZ BINCLOS
|
|||
|
CMP BX,[BYTCNT] ;Is memory full?
|
|||
|
JNZ PUTZ
|
|||
|
CALL FLSHFIL ;Empty it to make room for 1 lousy byte
|
|||
|
XOR BX,BX
|
|||
|
PUTZ:
|
|||
|
PUSH DS
|
|||
|
MOV DS,[TPA]
|
|||
|
MOV WORD PTR[BX],1AH ;Add End-of-file mark (Ctrl-Z)
|
|||
|
POP DS
|
|||
|
INC [NXTADD]
|
|||
|
BINCLOS:
|
|||
|
CALL FLSHFIL
|
|||
|
CMP [INEXACT],0 ;Copy not exact?
|
|||
|
JNZ NODATE ;If so, don't copy date & time
|
|||
|
MOV SI,OFFSET TRANGROUP:DIRBUF+OFFDATE
|
|||
|
MOV DI,OFFSET TRANGROUP:DEST+OFFDATE ;Make date & time same as original
|
|||
|
MOVSW ;Copy date
|
|||
|
MOVSW ;Copy time
|
|||
|
NODATE:
|
|||
|
MOV DX,OFFSET TRANGROUP:DEST
|
|||
|
MOV AH,CLOSE
|
|||
|
INT 21H
|
|||
|
INC [FILECNT]
|
|||
|
RET50: RET
|
|||
|
|
|||
|
FLSHFIL:
|
|||
|
;Write out any data remaining in memory.
|
|||
|
; Inputs:
|
|||
|
; [NXTADD] = No. of bytes to write
|
|||
|
; [CFLAG] <>0 if file has been created
|
|||
|
; Outputs:
|
|||
|
; [NXTADD] = 0
|
|||
|
|
|||
|
MOV AL,1
|
|||
|
XCHG [CFLAG],AL
|
|||
|
OR AL,AL
|
|||
|
JNZ EXISTS
|
|||
|
CMP [NOWRITE],0
|
|||
|
JNZ SKPMAK ;Don't actually create if NOWRITE set
|
|||
|
MOV DX,OFFSET TRANGROUP:DEST
|
|||
|
MOV AH,MAKE
|
|||
|
INT 21H
|
|||
|
MOV DX,OFFSET TRANGROUP:FULDIR
|
|||
|
OR AL,AL
|
|||
|
JNZ COPERR
|
|||
|
SKPMAK:
|
|||
|
XOR AX,AX
|
|||
|
MOV WORD PTR[DEST+RR],AX
|
|||
|
MOV WORD PTR[DEST+RR+2],AX
|
|||
|
INC AX
|
|||
|
MOV WORD PTR[DEST+RECLEN],AX
|
|||
|
EXISTS:
|
|||
|
XOR CX,CX
|
|||
|
XCHG CX,[NXTADD]
|
|||
|
CMP [NOWRITE],0 ;If NOWRITE set, just seek CX bytes
|
|||
|
JNZ SEEKEND
|
|||
|
XOR DX,DX
|
|||
|
PUSH DS
|
|||
|
MOV DS,[TPA]
|
|||
|
MOV AH,SETDMA
|
|||
|
INT 33
|
|||
|
POP DS
|
|||
|
MOV DX,OFFSET TRANGROUP:DEST
|
|||
|
MOV AH,WRBLK
|
|||
|
INT 21H
|
|||
|
OR AL,AL
|
|||
|
JZ RET60
|
|||
|
MOV DX,OFFSET TRANGROUP:DEST
|
|||
|
MOV AH,CLOSE
|
|||
|
INT 21H
|
|||
|
MOV AH,DELETE
|
|||
|
INT 33
|
|||
|
MOV DX,OFFSET TRANGROUP:NOSPACE
|
|||
|
COPERR:
|
|||
|
MOV AH,9
|
|||
|
INT 21H
|
|||
|
JMP ENDCOPY
|
|||
|
|
|||
|
SEEKEND:
|
|||
|
ADD WORD PTR[DEST+RR],CX
|
|||
|
ADC WORD PTR[DEST+RR+2],0 ;Propagate carry
|
|||
|
RET60: RET
|
|||
|
|
|||
|
GETBATBYT:
|
|||
|
;Get one byte from the batch file and return it in AL. End-of-file
|
|||
|
;returns <CR> and ends batch mode. DS must be set to resident segment.
|
|||
|
;AH, CX, DX destroyed.
|
|||
|
ASSUME DS:RESGROUP
|
|||
|
MOV DX,OFFSET RESGROUP:BATFCB
|
|||
|
MOV AH,RDBLK
|
|||
|
MOV CX,1
|
|||
|
INT 33 ;Get one more byte from batch file
|
|||
|
JCXZ BATEOF
|
|||
|
MOV AL,[BATBYT]
|
|||
|
CMP AL,1AH
|
|||
|
JNZ RET70
|
|||
|
BATEOF:
|
|||
|
MOV AL,0DH ;If end-of-file, then end of line
|
|||
|
MOV [BATCH],0 ;And turn off batch mode
|
|||
|
RET70: RET
|
|||
|
ASSUME DS:TRANGROUP
|
|||
|
|
|||
|
SCANOFF:
|
|||
|
LODSB
|
|||
|
CALL DELIM
|
|||
|
JZ SCANOFF
|
|||
|
DEC SI ;Point to first non-delimiter
|
|||
|
RET
|
|||
|
|
|||
|
DELIM:
|
|||
|
CMP AL," "
|
|||
|
JZ RET80
|
|||
|
CMP AL,"="
|
|||
|
JZ RET80
|
|||
|
CMP AL,","
|
|||
|
JZ RET80
|
|||
|
CMP AL,9 ;Check for TAB character
|
|||
|
RET80: RET
|
|||
|
|
|||
|
PAUSE:
|
|||
|
MOV DX,OFFSET TRANGROUP:PAUSMES
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 33
|
|||
|
MOV AX,0C00H+INCHAR ;Get character with KB buffer flush
|
|||
|
INT 33
|
|||
|
RET90: RET
|
|||
|
|
|||
|
;Date and time are set during initialization and use
|
|||
|
;this routines since they need to do a long return
|
|||
|
|
|||
|
DATINIT:
|
|||
|
PUSH ES
|
|||
|
PUSH DS ;Going to use the previous stack
|
|||
|
MOV AX,CS ;Set up the appropriate segment registers
|
|||
|
MOV ES,AX
|
|||
|
MOV DS,AX
|
|||
|
MOV WORD PTR DS:[81H],13 ;Want to prompt for date during initialization
|
|||
|
CALL DATE
|
|||
|
CALL TIME
|
|||
|
POP DS
|
|||
|
POP ES
|
|||
|
YYY PROC FAR
|
|||
|
RET
|
|||
|
YYY ENDP
|
|||
|
|
|||
|
; DATE - Gets and sets the time
|
|||
|
|
|||
|
DATE:
|
|||
|
MOV SI,81H ;Accepting argument for date inline
|
|||
|
CALL SCANOFF
|
|||
|
CMP AL,13
|
|||
|
JZ PRMTDAT
|
|||
|
MOV BX,2F00H+"-" ;"/-"
|
|||
|
CALL INLINE
|
|||
|
JMP COMDAT
|
|||
|
|
|||
|
PRMTDAT:
|
|||
|
MOV DX,OFFSET TRANGROUP:CURDAT
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 33 ;Print "Current date is "
|
|||
|
MOV AH,GETDATE
|
|||
|
INT 33 ;Get date in CX:DX
|
|||
|
CBW
|
|||
|
MOV SI,AX
|
|||
|
SHL SI,1
|
|||
|
ADD SI,AX ;SI=AX*3
|
|||
|
ADD SI,OFFSET TRANGROUP:WEEKTAB
|
|||
|
MOV BX,CX
|
|||
|
MOV CX,3
|
|||
|
CALL OUTCNT
|
|||
|
MOV AL," "
|
|||
|
CALL OUT
|
|||
|
MOV AX,BX
|
|||
|
MOV CX,DX
|
|||
|
MOV DL,100
|
|||
|
DIV DL
|
|||
|
XCHG AL,AH
|
|||
|
XCHG AX,DX
|
|||
|
MOV BL,"-"
|
|||
|
CALL SHOW
|
|||
|
GETDAT:
|
|||
|
MOV DX,OFFSET TRANGROUP:NEWDAT
|
|||
|
MOV BX,2F00H+"-" ;"/-" in BX
|
|||
|
CALL GETBUF
|
|||
|
COMDAT: JZ RET90
|
|||
|
JC DATERR
|
|||
|
LODSB
|
|||
|
CMP AL,BL
|
|||
|
JZ SEPGD
|
|||
|
CMP AL,BH
|
|||
|
JNZ DATERR
|
|||
|
SEPGD: CALL GETNUM
|
|||
|
JC DATERR
|
|||
|
MOV CX,1900
|
|||
|
CMP BYTE PTR[SI],13
|
|||
|
JZ BIAS
|
|||
|
MOV AL,100
|
|||
|
MUL AH
|
|||
|
MOV CX,AX
|
|||
|
CALL GETNUM
|
|||
|
JC DATERR
|
|||
|
BIAS:
|
|||
|
MOV AL,AH
|
|||
|
MOV AH,0
|
|||
|
ADD CX,AX
|
|||
|
LODSB
|
|||
|
CMP AL,13
|
|||
|
JNZ DATERR
|
|||
|
MOV AH,SETDATE
|
|||
|
INT 33
|
|||
|
OR AL,AL
|
|||
|
JNZ DATERR
|
|||
|
JMP RET90
|
|||
|
DATERR:
|
|||
|
MOV DX,OFFSET TRANGROUP:BADDAT
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 33
|
|||
|
JMP GETDAT
|
|||
|
|
|||
|
; TIME gets and sets the time
|
|||
|
|
|||
|
TIME:
|
|||
|
MOV SI,81H ;Accepting argument for time inline
|
|||
|
CALL SCANOFF
|
|||
|
CMP AL,13
|
|||
|
JZ PRMTTIM
|
|||
|
MOV BX,3A00H+":"
|
|||
|
CALL INLINE
|
|||
|
JMP COMTIM
|
|||
|
|
|||
|
PRMTTIM:
|
|||
|
MOV DX,OFFSET TRANGROUP:CURTIM
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 33 ;Print "Current time is "
|
|||
|
MOV AH,GETTIME
|
|||
|
INT 33 ;Get time in CX:DX
|
|||
|
MOV BL,":"
|
|||
|
CALL SHOW
|
|||
|
GETTIM:
|
|||
|
XOR CX,CX ;Initialize hours and minutes to zero
|
|||
|
MOV DX,OFFSET TRANGROUP:NEWTIM
|
|||
|
MOV BX,3A00H+":"
|
|||
|
CALL GETBUF
|
|||
|
COMTIM: JZ RET100 ;If no time present, don't change it
|
|||
|
JC TIMERR
|
|||
|
MOV CX,DX
|
|||
|
XOR DX,DX
|
|||
|
LODSB
|
|||
|
CMP AL,13
|
|||
|
JZ SAVTIM
|
|||
|
CMP AL,BL
|
|||
|
JNZ TIMERR
|
|||
|
MOV BL,"."
|
|||
|
CALL GETNUM
|
|||
|
JC TIMERR
|
|||
|
MOV DH,AH ;Position seconds
|
|||
|
LODSB
|
|||
|
CMP AL,13
|
|||
|
JZ SAVTIM
|
|||
|
CMP AL,BL
|
|||
|
JNZ TIMERR
|
|||
|
CALL GETNUM
|
|||
|
JC TIMERR
|
|||
|
MOV DL,AH
|
|||
|
LODSB
|
|||
|
CMP AL,13
|
|||
|
JNZ TIMERR
|
|||
|
SAVTIM:
|
|||
|
MOV AH,SETTIME
|
|||
|
INT 33
|
|||
|
OR AL,AL
|
|||
|
JZ RET100 ;Error in time?
|
|||
|
TIMERR:
|
|||
|
MOV DX,OFFSET TRANGROUP:BADTIM
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 33 ;Print error message
|
|||
|
JMP GETTIM ;Try again
|
|||
|
|
|||
|
GETBUF:
|
|||
|
MOV AH,PRINTBUF
|
|||
|
INT 33 ;Print "Enter new date: "
|
|||
|
MOV AH,INBUF
|
|||
|
MOV DX,OFFSET TRANGROUP:COMBUF
|
|||
|
INT 33 ;Get input line
|
|||
|
CALL CRLF2
|
|||
|
MOV SI,OFFSET TRANGROUP:COMBUF+2
|
|||
|
CMP BYTE PTR[SI],13 ;Check if new date entered
|
|||
|
JZ RET100
|
|||
|
INLINE:
|
|||
|
CALL GETNUM ;Get one or two digit number
|
|||
|
JC RET100
|
|||
|
MOV DH,AH ;Put in position
|
|||
|
LODSB
|
|||
|
CMP AL,BL
|
|||
|
JZ NEXT
|
|||
|
CMP BL,":" ;Is it a date seperator?
|
|||
|
JNZ DATESEP
|
|||
|
DEC SI
|
|||
|
MOV DL,0
|
|||
|
RET100: RET ;Time may have only an hour specified
|
|||
|
DATESEP:
|
|||
|
CMP AL,BH
|
|||
|
STC
|
|||
|
JNZ RET100
|
|||
|
NEXT: CALL GETNUM
|
|||
|
MOV DL,AH ;Put in position
|
|||
|
RET
|
|||
|
|
|||
|
GETNUM:
|
|||
|
CALL INDIG
|
|||
|
JC RET100
|
|||
|
MOV AH,AL ;Save first digit
|
|||
|
CALL INDIG ;Another digit?
|
|||
|
JC OKRET
|
|||
|
AAD ;Convert unpacked BCD to decimal
|
|||
|
MOV AH,AL
|
|||
|
OKRET:
|
|||
|
OR AL,1
|
|||
|
RET110: RET
|
|||
|
|
|||
|
INDIG:
|
|||
|
MOV AL,BYTE PTR[SI]
|
|||
|
SUB AL,"0"
|
|||
|
JC RET110
|
|||
|
CMP AL,10
|
|||
|
CMC
|
|||
|
JC RET110
|
|||
|
INC SI
|
|||
|
RET
|
|||
|
|
|||
|
SHOW:
|
|||
|
MOV AL,CH
|
|||
|
MOV BH,"0"-" " ;Enable leading zero suppression
|
|||
|
CALL OUT2
|
|||
|
MOV AL,BL
|
|||
|
CALL OUT
|
|||
|
MOV AL,CL
|
|||
|
CALL OUT2
|
|||
|
MOV AL,BL
|
|||
|
CALL OUT
|
|||
|
MOV AL,DH
|
|||
|
CALL OUT2
|
|||
|
CMP BL,":" ;Are we outputting time?
|
|||
|
JNZ SKIPIT
|
|||
|
MOV AL,"."
|
|||
|
CALL OUT
|
|||
|
SKIPIT: MOV AL,DL
|
|||
|
OUT2: ;Output binary number as two ASCII digits
|
|||
|
AAM ;Convert binary to unpacked BCD
|
|||
|
XCHG AL,AH
|
|||
|
OR AX,3030H ;Add "0" bias to both digits
|
|||
|
CMP AL,"0" ;Is MSD zero?
|
|||
|
JNZ NOSUP
|
|||
|
SUB AL,BH ;Suppress leading zero if enabled
|
|||
|
NOSUP:
|
|||
|
MOV BH,0 ;Disable zero suppression
|
|||
|
CALL OUT
|
|||
|
MOV AL,AH
|
|||
|
OUT:
|
|||
|
;Print char in AL without affecting registers
|
|||
|
XCHG AX,DX
|
|||
|
PUSH AX
|
|||
|
MOV AH,OUTCH
|
|||
|
INT 33
|
|||
|
POP AX
|
|||
|
XCHG AX,DX
|
|||
|
RET
|
|||
|
|
|||
|
EXELOAD:
|
|||
|
MOV AX,CS
|
|||
|
ADD AX,LOADSEG
|
|||
|
MOV [EXEEND],AX ;Store in EXEEND
|
|||
|
MOV DX,OFFSET TRANGROUP:RUNVAR ;Read header in here
|
|||
|
MOV AH,SETDMA
|
|||
|
INT 33
|
|||
|
MOV CX,RUNVARSIZ ;Amount of header info we need
|
|||
|
MOV DX,OFFSET TRANGROUP:EXEFCB
|
|||
|
MOV AH,RDBLK
|
|||
|
INT 33 ;Read in header
|
|||
|
OR AL,AL
|
|||
|
JNZ BADEXE ;Must not reach EOF
|
|||
|
MOV AX,[HEADSIZ] ;Size of header in paragraphs
|
|||
|
;Convert header size to 512-byte pages by multiplying by 32 & rounding up
|
|||
|
ADD AX,31 ;Round up first
|
|||
|
MOV CL,5
|
|||
|
SHR AX,CL ;Multiply by 32
|
|||
|
MOV [EXEFCB+RR],AX ;Position in file of program
|
|||
|
MOV WORD PTR[EXEFCB+RECLEN],512 ;Set record size
|
|||
|
ADD BX,10H ;First paragraph above parameter area
|
|||
|
MOV DX,[PAGES] ;Total size of file in 512-byte pages
|
|||
|
SUB DX,AX ;Size of program in pages
|
|||
|
MOV [PSIZE],DX
|
|||
|
SHL DX,CL ;Convert pages back to paragraphs
|
|||
|
MOV AX,DX
|
|||
|
ADD DX,BX ;Size + start = minimum memory (paragr.)
|
|||
|
MOV CX,[EXEEND] ;Get memory size in paragraphs
|
|||
|
CMP DX,CX ;Enough memory?
|
|||
|
JA SHRTERR
|
|||
|
MOV DX,[INITSP]
|
|||
|
ADD DX,15
|
|||
|
SHR DX,1
|
|||
|
SHR DX,1
|
|||
|
SHR DX,1
|
|||
|
SHR DX,1
|
|||
|
ADD DX,[INITSS]
|
|||
|
ADD DX,BX ;Adjusted value of SP
|
|||
|
CMP DX,CX ;Is it valid?
|
|||
|
JA SHRTERR
|
|||
|
CMP [LOADLOW],-1 ;Load low or high?
|
|||
|
JZ LOAD ;If low, load at segment BX
|
|||
|
SUB CX,AX ;Memory size - program size = load addr.
|
|||
|
MOV BX,CX
|
|||
|
LOAD:
|
|||
|
MOV BP,BX ;Save load segment
|
|||
|
LOAD1:
|
|||
|
LOADSEG EQU (LOAD1-ZERO)/16
|
|||
|
PUSH DS
|
|||
|
MOV DS,BX
|
|||
|
XOR DX,DX ;Address 0 in segment
|
|||
|
MOV AH,SETDMA
|
|||
|
INT 33 ;Set load address
|
|||
|
POP DS
|
|||
|
MOV CX,[PSIZE] ;Number of records to read
|
|||
|
MOV DX,OFFSET TRANGROUP:EXEFCB
|
|||
|
MOV AH,RDBLK
|
|||
|
INT 33 ;Read in up to 64K
|
|||
|
SUB [PSIZE],CX ;Decrement count by amount read
|
|||
|
JZ HAVEXE ;Did we get it all?
|
|||
|
TEST AL,1 ;Check return code if not
|
|||
|
JNZ BADEXE ;Must be zero if more to come
|
|||
|
ADD BX,1000H-20H ;Bump data segment 64K minus one record
|
|||
|
JMP SHORT LOAD1 ;Get next 64K block
|
|||
|
|
|||
|
BADEXE:
|
|||
|
MOV DX,OFFSET TRANGROUP:EXEBAD
|
|||
|
JMP ERROR
|
|||
|
|
|||
|
SHRTERR:
|
|||
|
MOV DX,OFFSET TRANGROUP:TOOBIG
|
|||
|
JMP ERROR
|
|||
|
|
|||
|
HAVEXE:
|
|||
|
MOV AX,[RELTAB] ;Get position of table
|
|||
|
MOV [EXEFCB+RR],AX ;Set in random record field
|
|||
|
MOV WORD PTR[EXEFCB+RECLEN],1 ;Set one-byte record
|
|||
|
MOV DX,OFFSET TRANGROUP:RELPT ;4-byte buffer for relocation address
|
|||
|
MOV AH,SETDMA
|
|||
|
INT 33
|
|||
|
CMP [RELCNT],0
|
|||
|
JZ NOREL
|
|||
|
RELOC:
|
|||
|
MOV AH,RDBLK
|
|||
|
MOV DX,OFFSET TRANGROUP:EXEFCB
|
|||
|
MOV CX,4
|
|||
|
INT 33 ;Read in one relocation pointer
|
|||
|
OR AL,AL ;Check return code
|
|||
|
JNZ BADEXE
|
|||
|
MOV DI,[RELPT] ;Get offset of relocation pointer
|
|||
|
MOV AX,[RELSEG] ;Get segment
|
|||
|
ADD AX,BP ;Bias segment with actual load segment
|
|||
|
MOV ES,AX
|
|||
|
ADD WORD PTR ES:[DI],BP ;Relocate
|
|||
|
DEC [RELCNT] ;Count off
|
|||
|
JNZ RELOC
|
|||
|
;Set up exit conditions
|
|||
|
NOREL:
|
|||
|
MOV AX,[INITSS]
|
|||
|
ADD AX,BP
|
|||
|
CLI
|
|||
|
MOV SS,AX ;Initialize SS
|
|||
|
MOV SP,[INITSP]
|
|||
|
STI
|
|||
|
ADD [INITCS],BP
|
|||
|
MOV AX,[TPA] ;Get pointer to parameter area
|
|||
|
MOV CX,[BYTCNT] ;Size of TPA segment
|
|||
|
MOV ES,AX
|
|||
|
MOV DS,AX ;Set segment registers to point to it
|
|||
|
CALL SETUP
|
|||
|
JMP DWORD PTR CS:[INITIP] ;Long jump to program
|
|||
|
|
|||
|
SETUP:
|
|||
|
AND CL,0F0H ;Adjust to even paragraph boundary
|
|||
|
MOV AX,WORD PTR DS:[6] ;Get current memory size
|
|||
|
SUB AX,CX ;Find out how much we're changing it
|
|||
|
MOV WORD PTR DS:[6],CX
|
|||
|
MOV CL,4
|
|||
|
SAR AX,CL ;Convert to a segment address
|
|||
|
ADD WORD PTR DS:[8],AX ;Adjust long jump to go to same place
|
|||
|
MOV DX,80H
|
|||
|
MOV AH,SETDMA
|
|||
|
INT 33 ;Set default disk transfer address
|
|||
|
MOV AX,WORD PTR CS:[PARM1] ;Pass on info about FCBs
|
|||
|
XOR CX,CX
|
|||
|
MOV DX,CX ;Assume no batch file
|
|||
|
ASSUME CS:RESGROUP
|
|||
|
TEST CS:[BATCH],-1 ;Batch file in progress?
|
|||
|
ASSUME CS:TRANGROUP
|
|||
|
JZ RET120 ;If not, all set up
|
|||
|
MOV CX,CS:[RESSEG]
|
|||
|
MOV DX,OFFSET RESGROUP:BATFCB ;CX:DX points to batch FCB
|
|||
|
RET120: RET
|
|||
|
TRANCODESIZE EQU $-ZERO
|
|||
|
TRANCODE ENDS
|
|||
|
COMLEN EQU TRANDATASIZE+TRANCODESIZE-102H ;End of COMMAND load. ZERO Needed to make COMLEN absolute
|
|||
|
TRNLEN EQU (PRETRLEN+TRANCODESIZE+TRANDATASIZE+15)/16 ;Length of transient in paragraphs
|
|||
|
END PROGSTART
|
|||
|
|