mirror of
https://github.com/microsoft/MS-DOS.git
synced 2024-11-25 07:05:45 +00:00
1645 lines
45 KiB
NASM
1645 lines
45 KiB
NASM
|
;MS-DOS PRINT program for background printing of text files to the list
|
|||
|
; device. INT 28H is a software interrupt generated by the DOS
|
|||
|
; in its I/O wait loops. This spooler can be assembled for
|
|||
|
; operation using only this interrupt which is portable from
|
|||
|
; system to system. It may also be assembled to use a hardware
|
|||
|
; timer interrupt in addition to the software INT 28H. The
|
|||
|
; purpose of using hardware interrupts is to allow printing to
|
|||
|
; continue during programs which do not enter the system and
|
|||
|
; therefore causes the INT 28H to go away. A timer interrupt is
|
|||
|
; chosen in preference to a "printer buffer empty" interrupt
|
|||
|
; because PRINT in the timer form is generic. It can be given
|
|||
|
; the name of any currently installed character device as the
|
|||
|
; "printer", this makes it portable to devices which are
|
|||
|
; installed by the user even in the hardware case. It could be
|
|||
|
; modified to use a buffer empty interrupt (no code is given for
|
|||
|
; this case), if this is done the PROMPT and BADMES messages and
|
|||
|
; their associated code should be removed as PRINT will then be
|
|||
|
; device specific.
|
|||
|
;
|
|||
|
; VERSION 1.00 07/03/82
|
|||
|
|
|||
|
|
|||
|
FALSE EQU 0
|
|||
|
TRUE EQU NOT FALSE
|
|||
|
|
|||
|
IBM EQU TRUE
|
|||
|
IBMVER EQU IBM
|
|||
|
MSVER EQU FALSE
|
|||
|
|
|||
|
IF MSVER
|
|||
|
HARDINT EQU FALSE ;No hardware ints
|
|||
|
AINT EQU FALSE ;No need to do interrupt acknowledge
|
|||
|
ENDIF
|
|||
|
|
|||
|
IF IBM
|
|||
|
HARDINT EQU TRUE
|
|||
|
INTLOC EQU 1CH ;Hardware interrupt location (Timer)
|
|||
|
AINT EQU TRUE ;Acknowledge interrupts
|
|||
|
EOI EQU 20H ;End Of Interrupt "instruction"
|
|||
|
AKPORT EQU 20H ;Interrupt Acknowledge port
|
|||
|
ENDIF
|
|||
|
|
|||
|
;The following values have to do with the ERRCNT variable and the
|
|||
|
; CNTMES message. The values define levels at wich it is assumed
|
|||
|
; an off-line error exists. ERRCNT1 defines the value of ERRCNT above
|
|||
|
; which the CNTMES message is printed by the transient. ERRCNT2
|
|||
|
; defines the value of ERRCNT above which the resident will give up
|
|||
|
; trying to print messages on the printer, it is much greater than
|
|||
|
; ERRCNT1 because a much tighter loop is involved. The bounding event
|
|||
|
; which determines the correct value is the time required to do a
|
|||
|
; form feed.
|
|||
|
|
|||
|
IF IBM
|
|||
|
ERRCNT1 EQU 1000
|
|||
|
ERRCNT2 EQU 20000
|
|||
|
ELSE
|
|||
|
ERRCNT1 EQU 1000
|
|||
|
ERRCNT2 EQU 20000
|
|||
|
ENDIF
|
|||
|
|
|||
|
IF HARDINT
|
|||
|
TIMESLICE EQU 8 ;The PRINT scheduling time slice. PRINT
|
|||
|
; lets this many "ticks" go by before
|
|||
|
; using a time slice to pump out characters.
|
|||
|
; Setting this to 3 for instance means PRINT
|
|||
|
; Will skip 3 slices, then take the fourth.
|
|||
|
; Thus using up 1/4 of the CPU. Setting it
|
|||
|
; to one gives PRINT 1/2 of the CPU.
|
|||
|
; The above examples assume MAXTICK is
|
|||
|
; 1. The actual PRINT CPU percentage is
|
|||
|
; (MAXTICK/(1+TIMESLICE))*100
|
|||
|
|
|||
|
MAXTICK EQU 2 ;The PRINT in timeslice. PRINT will pump
|
|||
|
; out characters for this many clock ticks
|
|||
|
; and then exit. The selection of a value
|
|||
|
; for this is dependent on the timer rate.
|
|||
|
|
|||
|
BUSYTICK EQU 1 ;If PRINT sits in a wait loop waiting for
|
|||
|
; output device to come ready for this
|
|||
|
; many ticks, it gives up its time slice.
|
|||
|
; Setting it greater than or equal to
|
|||
|
; MAXTICK causes it to be ignored.
|
|||
|
|
|||
|
;User gets TIMESLICE ticks and then PRINT takes MAXTICK ticks unless BUSYTICK
|
|||
|
; ticks go by without getting a character out.
|
|||
|
ENDIF
|
|||
|
|
|||
|
|
|||
|
;WARNING DANGER WARNING:
|
|||
|
; PRINT is a systems utility. It is clearly understood that it may have
|
|||
|
; to be entirely re-written for future versions of MS-DOS. The following
|
|||
|
; TWO vectors are version specific, they may not exist at all in future
|
|||
|
; versions. If they do exist, they may function differently.
|
|||
|
; ANY PROGRAM WHICH IMITATES PRINTS USE OF THESE VECTORS IS ALSO A SYSTEMS
|
|||
|
; UTILITY AND IS THEREFORE NOT VERSION PORTABLE IN ANY WAY SHAPE OR FORM.
|
|||
|
; YOU HAVE BEEN WARNED, "I DID IT THE SAME WAY PRINT DID" IS NOT AN REASON
|
|||
|
; TO EXPECT A PROGRAM TO WORK ON FUTURE VERSIONS OF MS-DOS.
|
|||
|
SOFTINT EQU 28H ;Software interrupt generated by DOS
|
|||
|
COMINT EQU 2FH ;Communications interrupt used by PRINT
|
|||
|
; This vector number is DOS reserved. It
|
|||
|
; is not generally available to programs
|
|||
|
; other than PRINT.
|
|||
|
|
|||
|
BLKSIZ EQU 512 ;Size of the PRINT I/O block in bytes
|
|||
|
FCBSIZ EQU 40 ;Size of an FCB
|
|||
|
|
|||
|
INCLUDE DOSSYM.ASM
|
|||
|
|
|||
|
FCB EQU 5CH
|
|||
|
PARMS EQU 80H
|
|||
|
|
|||
|
DG GROUP CODE,DATA
|
|||
|
|
|||
|
CODE SEGMENT
|
|||
|
ASSUME CS:DG
|
|||
|
|
|||
|
ORG 100H
|
|||
|
START:
|
|||
|
JMP TRANSIENT
|
|||
|
|
|||
|
HEADER DB "Vers 1.00"
|
|||
|
|
|||
|
DB 128 DUP (?)
|
|||
|
ISTACK LABEL WORD ;Stack starts here and grows down
|
|||
|
|
|||
|
;Resident data
|
|||
|
|
|||
|
IF HARDINT
|
|||
|
INDOS DD ? ;DOS buisy flag
|
|||
|
NEXTINT DD ? ;Chain for int
|
|||
|
BUSY DB 0 ;Internal ME flag
|
|||
|
SOFINT DB 0 ;Internal ME flag
|
|||
|
TICKCNT DB 0 ;Tick counter
|
|||
|
TICKSUB DB 0 ;Tick miss counter
|
|||
|
SLICECNT DB TIMESLICE ;Time slice counter
|
|||
|
ENDIF
|
|||
|
|
|||
|
CBUSY DB 0 ;ME on com interrupt
|
|||
|
SPNEXT DD ? ;Chain location for INT 28
|
|||
|
PCANMES DB 0 ;Cancel message flag
|
|||
|
SSsave DW ? ;Stack save area for INT 24
|
|||
|
SPsave DW ?
|
|||
|
DMAADDR DD ? ;Place to save DMA address
|
|||
|
HERRINT DD ? ;Place to save Hard error interrupt
|
|||
|
LISTDEV DD ? ;Pointer to Device
|
|||
|
COLPOS DB 0 ;Column position for TAB processing
|
|||
|
NXTCHR DW OFFSET DG:BUFFER + BLKSIZ ;Buffer pointer
|
|||
|
CURRFIL DW OFFSET DG:SPLFCB ;Current file being printed
|
|||
|
|
|||
|
LASTFCB DW ? ;Back pointer
|
|||
|
LASTFCB2 DW ? ;Another back pointer
|
|||
|
PABORT DB 0 ;Abort flag
|
|||
|
|
|||
|
;Resident messages
|
|||
|
|
|||
|
ERRMES DB 13,10,13,10,"**********",13,10,"$"
|
|||
|
ERRMEST DB " error reading file",13,10
|
|||
|
EMFILNAM DB " : . "
|
|||
|
BELMES DB 13,0CH,7,"$"
|
|||
|
|
|||
|
CANMES DB 13,10,13,10
|
|||
|
CANFILNAM DB " : . "
|
|||
|
DB " Canceled by operator$"
|
|||
|
|
|||
|
ALLCAN DB 13,10,13,10,"All files canceled by operator$"
|
|||
|
|
|||
|
MESBAS DW OFFSET DG:ERR0
|
|||
|
DW OFFSET DG:ERR1
|
|||
|
DW OFFSET DG:ERR2
|
|||
|
DW OFFSET DG:ERR3
|
|||
|
DW OFFSET DG:ERR4
|
|||
|
DW OFFSET DG:ERR5
|
|||
|
DW OFFSET DG:ERR6
|
|||
|
DW OFFSET DG:ERR7
|
|||
|
DW OFFSET DG:ERR8
|
|||
|
DW OFFSET DG:ERR9
|
|||
|
DW OFFSET DG:ERR10
|
|||
|
DW OFFSET DG:ERR11
|
|||
|
DW OFFSET DG:ERR12
|
|||
|
|
|||
|
;INT 24 messages A La COMMAND
|
|||
|
|
|||
|
ERR0 DB "Write protect$"
|
|||
|
ERR1 DB "Bad unit$"
|
|||
|
ERR2 DB "Not ready$"
|
|||
|
ERR3 DB "Bad command$"
|
|||
|
ERR4 DB "Data$"
|
|||
|
ERR5 DB "Bad call format$"
|
|||
|
ERR6 DB "Seek$"
|
|||
|
ERR7 DB "Non-DOS disk$"
|
|||
|
ERR8 DB "Sector not found$"
|
|||
|
ERR9 DB "No paper$"
|
|||
|
ERR10 DB "Write fault$"
|
|||
|
ERR11 DB "Read fault$"
|
|||
|
ERR12 DB "Disk$"
|
|||
|
|
|||
|
FATMES DB "File allocation table bad drive "
|
|||
|
BADDRVM DB "A.",13,10,"$"
|
|||
|
|
|||
|
;The DATA buffer
|
|||
|
BUFFER DB BLKSIZ DUP(0)
|
|||
|
DB ?
|
|||
|
CODE ENDS
|
|||
|
|
|||
|
;Transient data
|
|||
|
|
|||
|
DATA SEGMENT BYTE
|
|||
|
ORG 0
|
|||
|
SWITCHAR DB ? ;User switch character
|
|||
|
FULLFLAG DB 0 ;Flag for printing queue full message
|
|||
|
MAKERES DB 0 ;Flag to indicate presence of resident
|
|||
|
ARGSETUP DB 0 ;Flag to indicate a formatted FCB exists at 5C
|
|||
|
DEFDRV DB 0 ;Default drive
|
|||
|
CANFLG DB 0 ;Flag to indicate cancel
|
|||
|
FILCNT DB 0 ;Number of files
|
|||
|
SPLIST DD ? ;Pointer to FCBs in resident
|
|||
|
CURFILE DD ? ;Pointer to current FCB
|
|||
|
SRCHFCB DB 38 DUP (0) ;SEARCH-FIRST/NEXT FCB
|
|||
|
ENDRES DW OFFSET DG:DEF_ENDRES ;Term-Res location
|
|||
|
|
|||
|
;Messages
|
|||
|
|
|||
|
NOFILS DB "PRINT queue is empty",13,10,"$"
|
|||
|
CURMES DB 13,10," "
|
|||
|
CURFNAM DB " : . is currently being printed",13,10,"$"
|
|||
|
FILMES DB " "
|
|||
|
FILFNAM DB " : . is in queue"
|
|||
|
CRLF DB 13,10,"$"
|
|||
|
OPMES DB "Cannot open "
|
|||
|
OPFILNAM DB " : . ",13,10,"$"
|
|||
|
FULLMES DB "PRINT queue is full",13,10,"$"
|
|||
|
SRCHMES LABEL BYTE
|
|||
|
SRCHFNAM DB " : . "," File not found",13,10,"$"
|
|||
|
BADMES DB "List output is not assigned to a device",13,10,"$"
|
|||
|
GOODMES DB "Resident part of PRINT installed",13,10,"$"
|
|||
|
PROMPT DB "Name of list device [PRN]: $"
|
|||
|
CNTMES DB "Errors on list device indicate that it",13,10
|
|||
|
DB "may be off-line. Please check it.",13,10,13,10,"$"
|
|||
|
BADSWT DB "Invalid parameter",13,10,"$"
|
|||
|
|
|||
|
|
|||
|
BADVER DB "Incorrect DOS version",13,10,"$"
|
|||
|
|
|||
|
IF IBM
|
|||
|
;Reserved names for parallel card
|
|||
|
INT_17_HITLIST LABEL BYTE
|
|||
|
DB 8,"PRN ",0
|
|||
|
DB 8,"LPT1 ",0
|
|||
|
DB 8,"LPT2 ",1
|
|||
|
DB 8,"LPT3 ",2
|
|||
|
DB 0
|
|||
|
;Reserved names for Async adaptor
|
|||
|
INT_14_HITLIST LABEL BYTE
|
|||
|
DB 8,"AUX ",0
|
|||
|
DB 8,"COM1 ",0
|
|||
|
DB 8,"COM2 ",1
|
|||
|
DB 0
|
|||
|
ENDIF
|
|||
|
|
|||
|
COMBUF DB 14,0 ;Device name buffer
|
|||
|
DB 14 DUP (?)
|
|||
|
LISTFCB DB 0,"PRN " ;Device name FCB
|
|||
|
DB 25 DUP (0)
|
|||
|
PARSEBUF DB 80 DUP (?) ;Parsing space
|
|||
|
|
|||
|
DATA ENDS
|
|||
|
|
|||
|
CODE SEGMENT
|
|||
|
ASSUME CS:DG,DS:DG,ES:DG,SS:DG
|
|||
|
|
|||
|
|
|||
|
;Interrupt routines
|
|||
|
ASSUME CS:DG,DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|||
|
IF HARDINT
|
|||
|
HDSPINT: ;Hardware interrupt entry point
|
|||
|
INC [TICKCNT] ;Tick
|
|||
|
INC [TICKSUB] ;Tick
|
|||
|
CMP [SLICECNT],0
|
|||
|
JZ TIMENOW
|
|||
|
DEC [SLICECNT] ;Count down
|
|||
|
JMP SHORT CHAININT ;Not time yet
|
|||
|
TIMENOW:
|
|||
|
CMP [BUSY],0 ;See if interrupting ourself
|
|||
|
JNZ CHAININT
|
|||
|
PUSH DS
|
|||
|
PUSH SI
|
|||
|
LDS SI,[INDOS] ;Check for making DOS calls
|
|||
|
CMP BYTE PTR [SI],0
|
|||
|
POP SI
|
|||
|
POP DS
|
|||
|
JNZ CHAININT ;DOS is Buisy
|
|||
|
INC [BUSY] ;Exclude furthur interrupts
|
|||
|
MOV [TICKCNT],0 ;Reset tick counter
|
|||
|
MOV [TICKSUB],0 ;Reset tick counter
|
|||
|
STI ;Keep things rolling
|
|||
|
|
|||
|
IF AINT
|
|||
|
MOV AL,EOI ;Acknowledge interrupt
|
|||
|
OUT AKPORT,AL
|
|||
|
ENDIF
|
|||
|
|
|||
|
CALL DOINT
|
|||
|
CLI
|
|||
|
MOV [SLICECNT],TIMESLICE ;Either soft or hard int resets time slice
|
|||
|
MOV [BUSY],0 ;Done, let others in
|
|||
|
CHAININT:
|
|||
|
JMP [NEXTINT] ;Chain to next clock routine
|
|||
|
ENDIF
|
|||
|
|
|||
|
|
|||
|
SPINT: ;INT 28H entry point
|
|||
|
IF HARDINT
|
|||
|
CMP [BUSY],0
|
|||
|
JNZ NXTSP
|
|||
|
INC [BUSY] ;Exclude hardware interrupt
|
|||
|
INC [SOFINT] ;Indicate a software int in progress
|
|||
|
ENDIF
|
|||
|
|
|||
|
STI ;Hardware interrupts ok on INT 28H entry
|
|||
|
CALL DOINT
|
|||
|
|
|||
|
IF HARDINT
|
|||
|
CLI
|
|||
|
MOV [SOFINT],0 ;Indicate INT done
|
|||
|
MOV [SLICECNT],TIMESLICE ;Either soft or hard int resets time slice
|
|||
|
MOV [BUSY],0
|
|||
|
ENDIF
|
|||
|
|
|||
|
NXTSP: JMP [SPNEXT] ;Chain to next INT 28
|
|||
|
|
|||
|
DOINT:
|
|||
|
PUSH SI
|
|||
|
MOV SI,[CURRFIL]
|
|||
|
INC SI
|
|||
|
INC SI
|
|||
|
CMP BYTE PTR CS:[SI],-1
|
|||
|
POP SI
|
|||
|
JNZ GOAHEAD
|
|||
|
JMP SPRET ;Nothing to do
|
|||
|
GOAHEAD:
|
|||
|
PUSH AX ;Need a working register
|
|||
|
MOV [SSsave],SS
|
|||
|
MOV [SPsave],SP
|
|||
|
MOV AX,CS
|
|||
|
CLI
|
|||
|
;Go to internal stack to prevent INT 24 overflowing system stack
|
|||
|
MOV SS,AX
|
|||
|
MOV SP,OFFSET DG:ISTACK
|
|||
|
STI
|
|||
|
PUSH ES
|
|||
|
PUSH DS
|
|||
|
PUSH BX
|
|||
|
PUSH CX
|
|||
|
PUSH DX
|
|||
|
PUSH SI
|
|||
|
PUSH DI
|
|||
|
PUSH CS
|
|||
|
POP DS
|
|||
|
ASSUME DS:DG
|
|||
|
|
|||
|
MOV BX,[NXTCHR]
|
|||
|
CMP BX,OFFSET DG:BUFFER + BLKSIZ
|
|||
|
JNZ PLOOP
|
|||
|
JMP READBUFF ;Buffer empty
|
|||
|
|
|||
|
PLOOP:
|
|||
|
IF HARDINT
|
|||
|
MOV BX,[NXTCHR]
|
|||
|
CMP BX,OFFSET DG:BUFFER + BLKSIZ
|
|||
|
JZ DONEJMP ;Buffer has become empty
|
|||
|
CMP [SOFINT],0
|
|||
|
JNZ STATCHK
|
|||
|
CMP [TICKCNT],MAXTICK ;Check our time slice
|
|||
|
JAE DONEJMP
|
|||
|
STATCHK:
|
|||
|
ENDIF
|
|||
|
|
|||
|
CALL PSTAT
|
|||
|
|
|||
|
IF HARDINT
|
|||
|
JZ DOCHAR ;Printer ready
|
|||
|
CMP [SOFINT],0
|
|||
|
ENDIF
|
|||
|
|
|||
|
JNZ DONEJMP ;If soft int give up
|
|||
|
|
|||
|
IF HARDINT
|
|||
|
CMP [TICKSUB],BUSYTICK ;Check our busy timeout
|
|||
|
JAE DONEJMP
|
|||
|
JMP PLOOP
|
|||
|
ENDIF
|
|||
|
|
|||
|
DOCHAR:
|
|||
|
MOV AL,BYTE PTR [BX]
|
|||
|
CMP AL,1AH ;^Z?
|
|||
|
JZ FILEOFJ ;CPM EOF
|
|||
|
CMP AL,0DH ;CR?
|
|||
|
JNZ NOTCR
|
|||
|
MOV [COLPOS],0
|
|||
|
NOTCR:
|
|||
|
CMP AL,9 ;TAB?
|
|||
|
JNZ NOTABDO
|
|||
|
MOV CL,[COLPOS]
|
|||
|
OR CL,0F8H
|
|||
|
NEG CL
|
|||
|
XOR CH,CH
|
|||
|
JCXZ TABDONE
|
|||
|
TABLP:
|
|||
|
MOV AL," "
|
|||
|
INC [COLPOS]
|
|||
|
PUSH CX
|
|||
|
CALL POUT
|
|||
|
POP CX
|
|||
|
LOOP TABLP
|
|||
|
JMP TABDONE
|
|||
|
|
|||
|
NOTABDO:
|
|||
|
CMP AL,8 ;Back space?
|
|||
|
JNZ NOTBACK
|
|||
|
DEC [COLPOS]
|
|||
|
NOTBACK:
|
|||
|
CMP AL,20H ;Non Printing char?
|
|||
|
JB NOCHAR
|
|||
|
INC [COLPOS] ;Printing char
|
|||
|
NOCHAR:
|
|||
|
CALL POUT ;Print it
|
|||
|
TABDONE:
|
|||
|
INC [NXTCHR] ;Next char
|
|||
|
|
|||
|
IF HARDINT
|
|||
|
MOV [TICKSUB],0 ;Got a character out, Reset counter
|
|||
|
CMP [SOFINT],0 ;Soft int does one char at a time
|
|||
|
JZ PLOOP
|
|||
|
ENDIF
|
|||
|
|
|||
|
DONEJMP:
|
|||
|
POP DI
|
|||
|
POP SI
|
|||
|
POP DX
|
|||
|
POP CX
|
|||
|
POP BX
|
|||
|
POP DS
|
|||
|
POP ES
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
CLI
|
|||
|
MOV SS,[SSsave] ;Restore Entry Stack
|
|||
|
MOV SP,[SPsave]
|
|||
|
STI
|
|||
|
POP AX
|
|||
|
SPRET:
|
|||
|
RET
|
|||
|
|
|||
|
FILEOFJ: JMP FILEOF
|
|||
|
|
|||
|
READBUFF:
|
|||
|
ASSUME DS:DG,ES:NOTHING
|
|||
|
|
|||
|
MOV AL,24H
|
|||
|
MOV AH,GET_INTERRUPT_VECTOR
|
|||
|
INT 21H
|
|||
|
MOV WORD PTR [HERRINT+2],ES ;Save current vector
|
|||
|
MOV WORD PTR [HERRINT],BX
|
|||
|
MOV DX,OFFSET DG:DSKERR
|
|||
|
MOV AL,24H
|
|||
|
MOV AH,SET_INTERRUPT_VECTOR ;Install our own
|
|||
|
INT 21H ;Spooler must catch its errors
|
|||
|
MOV AH,GET_DMA
|
|||
|
INT 21H
|
|||
|
MOV WORD PTR [DMAADDR+2],ES ;Save DMA address
|
|||
|
MOV WORD PTR [DMAADDR],BX
|
|||
|
MOV DX,OFFSET DG:BUFFER
|
|||
|
MOV AH,SET_DMA
|
|||
|
INT 21H ;New DMA address
|
|||
|
MOV [PABORT],0 ;No abort
|
|||
|
MOV DX,[CURRFIL] ;Read
|
|||
|
INC DX
|
|||
|
INC DX ;Skip over pointer
|
|||
|
MOV AH,FCB_SEQ_READ
|
|||
|
INT 21H
|
|||
|
PUSH AX
|
|||
|
LDS DX,[DMAADDR]
|
|||
|
ASSUME DS:NOTHING
|
|||
|
MOV AH,SET_DMA
|
|||
|
INT 21H ;Restore DMA
|
|||
|
LDS DX,[HERRINT]
|
|||
|
MOV AL,24H
|
|||
|
MOV AH,SET_INTERRUPT_VECTOR
|
|||
|
INT 21H ;Restore Error INT
|
|||
|
POP AX
|
|||
|
PUSH CS
|
|||
|
POP DS
|
|||
|
ASSUME DS:DG
|
|||
|
CMP [PABORT],0
|
|||
|
JNZ TONEXTFIL ;Barf on this file, got INT 24
|
|||
|
CMP AL,01
|
|||
|
JZ FILEOF ;Read EOF?
|
|||
|
MOV BX,OFFSET DG:BUFFER ;Buffer full
|
|||
|
MOV [NXTCHR],BX
|
|||
|
JMP DONEJMP
|
|||
|
|
|||
|
FILEOF:
|
|||
|
MOV AL,0CH ;Form feed
|
|||
|
CALL LOUT
|
|||
|
TONEXTFIL:
|
|||
|
CALL NEXTFIL
|
|||
|
JMP DONEJMP
|
|||
|
|
|||
|
;INT 24 handler
|
|||
|
|
|||
|
DSKERR:
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|||
|
STI
|
|||
|
CMP [PABORT],0
|
|||
|
JNZ IGNRET
|
|||
|
PUSH BX
|
|||
|
PUSH CX
|
|||
|
PUSH DX
|
|||
|
PUSH DI
|
|||
|
PUSH SI
|
|||
|
PUSH BP
|
|||
|
PUSH ES
|
|||
|
PUSH DS
|
|||
|
PUSH CS
|
|||
|
POP DS
|
|||
|
PUSH CS
|
|||
|
POP ES
|
|||
|
ASSUME DS:DG,ES:DG
|
|||
|
ADD [BADDRVM],AL ;Set correct drive letter
|
|||
|
MOV SI,OFFSET DG:ERRMES
|
|||
|
CALL LISTMES
|
|||
|
TEST AH,080H
|
|||
|
JNZ FATERR
|
|||
|
AND DI,0FFH
|
|||
|
CMP DI,12
|
|||
|
JBE HAVCOD
|
|||
|
MOV DI,12
|
|||
|
HAVCOD:
|
|||
|
SHL DI,1
|
|||
|
MOV DI,WORD PTR [DI+MESBAS] ; Get pointer to error message
|
|||
|
MOV SI,DI
|
|||
|
CALL LISTMES ; Print error type
|
|||
|
MOV DI,OFFSET DG:EMFILNAM
|
|||
|
MOV SI,[CURRFIL]
|
|||
|
ADD SI,2 ;Get to file name
|
|||
|
LODSB
|
|||
|
ADD AL,'@'
|
|||
|
STOSB
|
|||
|
INC DI
|
|||
|
MOV CX,4
|
|||
|
REP MOVSW
|
|||
|
INC DI
|
|||
|
MOVSW
|
|||
|
MOVSB
|
|||
|
MOV SI,OFFSET DG:ERRMEST
|
|||
|
CALL LISTMES
|
|||
|
SETABORT:
|
|||
|
INC [PABORT] ;Indicate abort
|
|||
|
POP DS
|
|||
|
POP ES
|
|||
|
POP BP
|
|||
|
POP SI
|
|||
|
POP DI
|
|||
|
POP DX
|
|||
|
POP CX
|
|||
|
POP BX
|
|||
|
IGNRET:
|
|||
|
XOR AL,AL ;Ignore
|
|||
|
IRET
|
|||
|
|
|||
|
FATERR:
|
|||
|
MOV SI,OFFSET DG:FATMES
|
|||
|
CALL LISTMES
|
|||
|
JMP SHORT SETABORT
|
|||
|
|
|||
|
ADDFILJ: JMP ADDFIL
|
|||
|
|
|||
|
COMBUSY:
|
|||
|
MOV AX,-1
|
|||
|
IRET
|
|||
|
|
|||
|
;Communications interrupt
|
|||
|
SPCOMINT:
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|||
|
CMP [CBUSY],0
|
|||
|
JNZ COMBUSY
|
|||
|
INC [CBUSY] ;Exclude
|
|||
|
STI ;Turn ints back on
|
|||
|
PUSH SI
|
|||
|
PUSH DI
|
|||
|
PUSH CX
|
|||
|
PUSH DS
|
|||
|
PUSH CS
|
|||
|
POP DS
|
|||
|
ASSUME DS:DG
|
|||
|
MOV [PCANMES],0 ;Havn't printed cancel message
|
|||
|
OR AH,AH
|
|||
|
JZ ADDFILJ ;Add file
|
|||
|
CMP AH,1
|
|||
|
JZ CANFIL ;Cancel File(s)
|
|||
|
XOR AL,AL
|
|||
|
SETCOUNT:
|
|||
|
PUSH AX ;Save AL return code
|
|||
|
XOR AH,AH
|
|||
|
MOV SI,OFFSET DG:SPLFCB
|
|||
|
MOV CX,[NUMFCBS]
|
|||
|
CNTFILS:
|
|||
|
CMP BYTE PTR [SI+2],-1 ;Valid?
|
|||
|
JZ LNEXT
|
|||
|
INC AH
|
|||
|
LNEXT:
|
|||
|
ADD SI,FCBSIZ
|
|||
|
LOOP CNTFILS
|
|||
|
COMRET:
|
|||
|
MOV BX,OFFSET DG:SPLFCB
|
|||
|
MOV DX,[CURRFIL]
|
|||
|
PUSH DS
|
|||
|
POP ES
|
|||
|
ASSUME ES:NOTHING
|
|||
|
MOV CH,AH
|
|||
|
POP AX ;Get AL return
|
|||
|
MOV AH,CH
|
|||
|
|
|||
|
IF HARDINT
|
|||
|
BWAIT3:
|
|||
|
CMP [BUSY],0
|
|||
|
JNZ BWAIT3
|
|||
|
INC [BUSY]
|
|||
|
ENDIF
|
|||
|
|
|||
|
CALL PSTAT ; Tweek error counter
|
|||
|
|
|||
|
IF HARDINT
|
|||
|
MOV [BUSY],0
|
|||
|
ENDIF
|
|||
|
|
|||
|
POP DS
|
|||
|
ASSUME DS:NOTHING
|
|||
|
POP CX
|
|||
|
POP DI
|
|||
|
POP SI
|
|||
|
MOV [CBUSY],0
|
|||
|
IRET
|
|||
|
|
|||
|
DELALLJ: JMP DELALL
|
|||
|
|
|||
|
CANFIL:
|
|||
|
ASSUME DS:DG,ES:NOTHING
|
|||
|
MOV CX,[NUMFCBS]
|
|||
|
|
|||
|
IF HARDINT
|
|||
|
BWAIT:
|
|||
|
CMP [BUSY],0
|
|||
|
JNZ BWAIT
|
|||
|
INC [BUSY]
|
|||
|
ENDIF
|
|||
|
|
|||
|
MOV SI,[CURRFIL]
|
|||
|
CMP DX,-1
|
|||
|
JZ DELALLJ
|
|||
|
MOV BX,[SI]
|
|||
|
PUSH BX
|
|||
|
LOOKEND: ;Set initial pointer values
|
|||
|
CMP BX,SI
|
|||
|
JZ GOTLAST
|
|||
|
POP AX
|
|||
|
PUSH BX
|
|||
|
MOV BX,[BX]
|
|||
|
JMP SHORT LOOKEND
|
|||
|
|
|||
|
GOTLAST:
|
|||
|
POP BX
|
|||
|
MOV [LASTFCB],BX
|
|||
|
MOV [LASTFCB2],BX
|
|||
|
POP ES
|
|||
|
PUSH ES
|
|||
|
MOV BX,SI
|
|||
|
LOOKMATCH:
|
|||
|
MOV DI,DX
|
|||
|
ADD SI,2 ;Skip pointer
|
|||
|
CMP BYTE PTR [SI],-1
|
|||
|
JZ CANTERMJ ;No more
|
|||
|
CMPSB
|
|||
|
JNZ SKIPFIL ;DRIVE
|
|||
|
PUSH CX
|
|||
|
MOV CX,11
|
|||
|
NXTCHAR:
|
|||
|
MOV AL,ES:[DI]
|
|||
|
INC DI
|
|||
|
CALL UPCONV
|
|||
|
MOV AH,AL
|
|||
|
LODSB
|
|||
|
CALL UPCONV
|
|||
|
CMP AH,"?" ;Wild card?
|
|||
|
JZ NXTCHRLP ;Yes
|
|||
|
CMP AH,AL
|
|||
|
JNZ SKIPFILC
|
|||
|
NXTCHRLP:
|
|||
|
LOOP NXTCHAR
|
|||
|
MATCH:
|
|||
|
POP CX
|
|||
|
MOV AH,-1
|
|||
|
XCHG AH,[BX+2] ;Zap it
|
|||
|
CMP BX,[CURRFIL] ;Is current file?
|
|||
|
JNZ REQUEUE ;No
|
|||
|
MOV AL,1
|
|||
|
XCHG AL,[PCANMES]
|
|||
|
OR AL,AL
|
|||
|
JNZ DIDCMES ;Only print cancel message once
|
|||
|
PUSH ES
|
|||
|
PUSH CS
|
|||
|
POP ES
|
|||
|
MOV DI,OFFSET DG:CANFILNAM
|
|||
|
MOV SI,BX
|
|||
|
ADD SI,3 ;Get to file name
|
|||
|
MOV AL,AH
|
|||
|
ADD AL,'@'
|
|||
|
STOSB
|
|||
|
INC DI
|
|||
|
MOV CX,4
|
|||
|
REP MOVSW
|
|||
|
INC DI
|
|||
|
MOVSW
|
|||
|
MOVSB
|
|||
|
POP ES
|
|||
|
MOV SI,OFFSET DG:CANMES
|
|||
|
CALL LISTMES
|
|||
|
MOV SI,OFFSET DG:BELMES
|
|||
|
CALL LISTMES
|
|||
|
DIDCMES:
|
|||
|
PUSH CX
|
|||
|
CALL NEXTFIL
|
|||
|
SKIPFILC:
|
|||
|
POP CX
|
|||
|
SKIPFIL:
|
|||
|
MOV [LASTFCB2],BX
|
|||
|
MOV BX,[BX]
|
|||
|
NEXTFC:
|
|||
|
MOV SI,BX
|
|||
|
LOOP LOOKMATCH
|
|||
|
CANTERMJ: JMP SHORT CANTERM
|
|||
|
|
|||
|
REQUEUE:
|
|||
|
MOV AX,[BX]
|
|||
|
CMP AX,[CURRFIL] ;Is last FCB?
|
|||
|
JZ SKIPFIL ;Yes, is in right place
|
|||
|
MOV SI,[LASTFCB2]
|
|||
|
MOV [SI],AX ;Unlink FCB
|
|||
|
MOV SI,[CURRFIL]
|
|||
|
MOV [BX],SI
|
|||
|
MOV SI,[LASTFCB]
|
|||
|
MOV [SI],BX ;Link FCB at end
|
|||
|
MOV [LASTFCB],BX ;New end
|
|||
|
MOV BX,AX ;Process what it pointed to
|
|||
|
JMP SHORT NEXTFC
|
|||
|
|
|||
|
DELALL:
|
|||
|
CMP BYTE PTR CS:[SI+2],-1 ;Examine current file
|
|||
|
DELALL2:
|
|||
|
MOV BYTE PTR [SI+2],-1 ;Zap it
|
|||
|
MOV SI,[SI]
|
|||
|
LOOP DELALL2
|
|||
|
JZ CANTERM1 ;No message if nothing was in progress
|
|||
|
MOV SI,OFFSET DG:ALLCAN
|
|||
|
CALL LISTMES
|
|||
|
MOV SI,OFFSET DG:BELMES
|
|||
|
CALL LISTMES
|
|||
|
CANTERM1:
|
|||
|
MOV [NXTCHR],OFFSET DG:BUFFER + BLKSIZ ;Buffer empty
|
|||
|
CANTERM:
|
|||
|
|
|||
|
IF HARDINT
|
|||
|
MOV [BUSY],0
|
|||
|
ENDIF
|
|||
|
|
|||
|
XOR AX,AX
|
|||
|
JMP SETCOUNT
|
|||
|
|
|||
|
UPCONV:
|
|||
|
CMP AL,'a'
|
|||
|
JB NOCONV
|
|||
|
CMP AL,'z'
|
|||
|
JA NOCONV
|
|||
|
SUB AL,20H
|
|||
|
NOCONV:
|
|||
|
RET
|
|||
|
|
|||
|
ADDFIL:
|
|||
|
ASSUME DS:DG,ES:NOTHING
|
|||
|
MOV SI,[CURRFIL]
|
|||
|
MOV CX,[NUMFCBS]
|
|||
|
|
|||
|
IF HARDINT
|
|||
|
BWAIT2:
|
|||
|
CMP [BUSY],0
|
|||
|
JNZ BWAIT2
|
|||
|
INC [BUSY]
|
|||
|
ENDIF
|
|||
|
|
|||
|
LOOKSPOT:
|
|||
|
CMP BYTE PTR [SI+2],-1
|
|||
|
JZ GOTSPOT
|
|||
|
MOV SI,[SI]
|
|||
|
LOOP LOOKSPOT
|
|||
|
|
|||
|
IF HARDINT
|
|||
|
MOV [BUSY],0
|
|||
|
ENDIF
|
|||
|
|
|||
|
MOV AL,1
|
|||
|
JMP SETCOUNT
|
|||
|
|
|||
|
GOTSPOT:
|
|||
|
PUSH DS
|
|||
|
POP ES
|
|||
|
POP DS
|
|||
|
PUSH DS
|
|||
|
ASSUME DS:NOTHING
|
|||
|
PUSH SI
|
|||
|
MOV DI,SI
|
|||
|
ADD DI,2
|
|||
|
MOV SI,DX
|
|||
|
MOV CX,19
|
|||
|
REP MOVSW ;Copy in and set FCB
|
|||
|
POP SI
|
|||
|
PUSH ES
|
|||
|
POP DS
|
|||
|
ASSUME DS:DG
|
|||
|
MOV WORD PTR [SI+2+fcb_EXTENT],0
|
|||
|
MOV BYTE PTR [SI+2+fcb_NR],0
|
|||
|
MOV WORD PTR [SI+2+fcb_RECSIZ],BLKSIZ
|
|||
|
|
|||
|
IF HARDINT
|
|||
|
MOV [BUSY],0
|
|||
|
ENDIF
|
|||
|
|
|||
|
XOR AL,AL
|
|||
|
JMP SETCOUNT
|
|||
|
|
|||
|
NEXTFIL:
|
|||
|
ASSUME DS:DG,ES:NOTHING
|
|||
|
MOV SI,[CURRFIL]
|
|||
|
MOV BYTE PTR [SI+2],-1 ;Done with current file
|
|||
|
MOV SI,[SI]
|
|||
|
MOV [CURRFIL],SI
|
|||
|
MOV [NXTCHR],OFFSET DG:BUFFER + BLKSIZ ;Buffer empty
|
|||
|
MOV [COLPOS],0 ;Start of line
|
|||
|
RET
|
|||
|
|
|||
|
LISTMES:
|
|||
|
ASSUME DS:DG,ES:NOTHING
|
|||
|
LODSB
|
|||
|
CMP AL,"$"
|
|||
|
JZ LMESDONE
|
|||
|
CALL LOUT
|
|||
|
JMP LISTMES
|
|||
|
|
|||
|
LMESDONE:
|
|||
|
RET
|
|||
|
|
|||
|
LOUT:
|
|||
|
PUSH BX
|
|||
|
LWAIT:
|
|||
|
CALL PSTAT
|
|||
|
JZ PREADY
|
|||
|
CMP [ERRCNT],ERRCNT2
|
|||
|
JA POPRET ;Don't get stuck
|
|||
|
JMP SHORT LWAIT
|
|||
|
PREADY:
|
|||
|
CALL POUT
|
|||
|
POPRET:
|
|||
|
POP BX
|
|||
|
RET
|
|||
|
|
|||
|
;Stuff for BIOS interface
|
|||
|
IOBUSY EQU 0200H
|
|||
|
IOERROR EQU 8000H
|
|||
|
|
|||
|
BYTEBUF DB ?
|
|||
|
|
|||
|
CALLAD DD ?
|
|||
|
|
|||
|
IOCALL DB 22
|
|||
|
DB 0
|
|||
|
IOREQ DB ?
|
|||
|
IOSTAT DW 0
|
|||
|
DB 8 DUP(?)
|
|||
|
DB 0
|
|||
|
DW OFFSET DG:BYTEBUF
|
|||
|
INTSEG DW ?
|
|||
|
IOCNT DW 1
|
|||
|
DW 0
|
|||
|
|
|||
|
PSTAT:
|
|||
|
ASSUME DS:DG
|
|||
|
PUSH BX
|
|||
|
INC [ERRCNT]
|
|||
|
MOV BL,10
|
|||
|
CALL DOCALL
|
|||
|
TEST [IOSTAT],IOERROR
|
|||
|
JZ NOSTATERR
|
|||
|
OR [IOSTAT],IOBUSY ;If error, show buisy
|
|||
|
NOSTATERR:
|
|||
|
TEST [IOSTAT],IOBUSY
|
|||
|
JNZ RET13P ;Shows buisy
|
|||
|
MOV [ERRCNT],0
|
|||
|
RET13P:
|
|||
|
POP BX
|
|||
|
RET
|
|||
|
|
|||
|
POUT:
|
|||
|
ASSUME DS:DG
|
|||
|
MOV [BYTEBUF],AL
|
|||
|
MOV BL,8
|
|||
|
DOCALL:
|
|||
|
PUSH ES
|
|||
|
MOV [IOREQ],BL
|
|||
|
MOV BX,CS
|
|||
|
MOV ES,BX
|
|||
|
MOV BX,OFFSET DG:IOCALL
|
|||
|
MOV [IOSTAT],0
|
|||
|
MOV [IOCNT],1
|
|||
|
PUSH DS
|
|||
|
PUSH SI
|
|||
|
PUSH AX
|
|||
|
LDS SI,[LISTDEV]
|
|||
|
ASSUME DS:NOTHING
|
|||
|
MOV AX,[SI+6]
|
|||
|
MOV WORD PTR [CALLAD],AX
|
|||
|
CALL [CALLAD]
|
|||
|
MOV AX,[SI+8]
|
|||
|
MOV WORD PTR [CALLAD],AX
|
|||
|
CALL [CALLAD]
|
|||
|
POP AX
|
|||
|
POP SI
|
|||
|
POP DS
|
|||
|
ASSUME DS:DG
|
|||
|
POP ES
|
|||
|
RET
|
|||
|
|
|||
|
IF IBM
|
|||
|
REAL_INT_13 DD ?
|
|||
|
INT_13_RETADDR DW OFFSET DG:INT_13_BACK
|
|||
|
|
|||
|
INT_13 PROC FAR
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|||
|
PUSHF
|
|||
|
INC [BUSY] ;Exclude if dumb program call ROM
|
|||
|
PUSH CS
|
|||
|
PUSH [INT_13_RETADDR]
|
|||
|
PUSH WORD PTR [REAL_INT_13+2]
|
|||
|
PUSH WORD PTR [REAL_INT_13]
|
|||
|
RET
|
|||
|
INT_13 ENDP
|
|||
|
|
|||
|
INT_13_BACK PROC FAR
|
|||
|
PUSHF
|
|||
|
DEC [BUSY]
|
|||
|
POPF
|
|||
|
RET 2 ;Chuck saved flags
|
|||
|
INT_13_BACK ENDP
|
|||
|
ENDIF
|
|||
|
|
|||
|
|
|||
|
IF IBM
|
|||
|
|
|||
|
REAL_INT_5 DD ?
|
|||
|
REAL_INT_17 DD ?
|
|||
|
INT_17_NUM DW 0
|
|||
|
|
|||
|
INT_17:
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|||
|
PUSH SI
|
|||
|
MOV SI,[CURRFIL]
|
|||
|
INC SI
|
|||
|
INC SI
|
|||
|
CMP BYTE PTR CS:[SI],-1
|
|||
|
POP SI
|
|||
|
JZ DO_INT_17 ;Nothing pending, so OK
|
|||
|
CMP DX,[INT_17_NUM]
|
|||
|
JNZ DO_INT_17 ;Not my unit
|
|||
|
CMP [BUSY],0
|
|||
|
JNZ DO_INT_17 ;You are me
|
|||
|
STI
|
|||
|
MOV AH,0A1H ;You are bad, get out of paper
|
|||
|
IRET
|
|||
|
|
|||
|
DO_INT_17:
|
|||
|
JMP [REAL_INT_17] ;Do a 17
|
|||
|
|
|||
|
REAL_INT_14 DD ?
|
|||
|
INT_14_NUM DW 0
|
|||
|
|
|||
|
INT_14:
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|||
|
PUSH SI
|
|||
|
MOV SI,[CURRFIL]
|
|||
|
INC SI
|
|||
|
INC SI
|
|||
|
CMP BYTE PTR CS:[SI],-1
|
|||
|
POP SI
|
|||
|
JZ DO_INT_14 ;Nothing pending, so OK
|
|||
|
CMP DX,[INT_14_NUM]
|
|||
|
JNZ DO_INT_14 ;Not my unit
|
|||
|
CMP [BUSY],0
|
|||
|
JNZ DO_INT_14 ;You are me
|
|||
|
STI
|
|||
|
OR AH,AH
|
|||
|
JZ SET14_AX
|
|||
|
CMP AH,2
|
|||
|
JBE SET14_AH
|
|||
|
SET14_AX:
|
|||
|
MOV AL,0
|
|||
|
SET14_AH:
|
|||
|
MOV AH,80H ;Time out
|
|||
|
IRET
|
|||
|
|
|||
|
DO_INT_14:
|
|||
|
JMP [REAL_INT_14] ;Do a 14
|
|||
|
|
|||
|
INT_5:
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|||
|
PUSH SI
|
|||
|
MOV SI,[CURRFIL]
|
|||
|
INC SI
|
|||
|
INC SI
|
|||
|
CMP BYTE PTR CS:[SI],-1
|
|||
|
POP SI
|
|||
|
JZ DO_INT_5 ;Nothing pending, so OK
|
|||
|
CMP [INT_17_NUM],0
|
|||
|
JNZ DO_INT_5 ;Only care about unit 0
|
|||
|
IRET ;Pretend it worked
|
|||
|
|
|||
|
DO_INT_5:
|
|||
|
JMP [REAL_INT_5] ;Do a 5
|
|||
|
ENDIF
|
|||
|
|
|||
|
|
|||
|
;The following data is order and position dependant
|
|||
|
NUMFCBS DW 10
|
|||
|
ERRCNT DW 0
|
|||
|
|
|||
|
SPLFCB DW OFFSET DG:FC1
|
|||
|
DB (FCBSIZ - 2) DUP (-1)
|
|||
|
FC1 DW OFFSET DG:FC2
|
|||
|
DB (FCBSIZ - 2) DUP (-1)
|
|||
|
FC2 DW OFFSET DG:FC3
|
|||
|
DB (FCBSIZ - 2) DUP (-1)
|
|||
|
FC3 DW OFFSET DG:FC4
|
|||
|
DB (FCBSIZ - 2) DUP (-1)
|
|||
|
FC4 DW OFFSET DG:FC5
|
|||
|
DB (FCBSIZ - 2) DUP (-1)
|
|||
|
FC5 DW OFFSET DG:FC6
|
|||
|
DB (FCBSIZ - 2) DUP (-1)
|
|||
|
FC6 DW OFFSET DG:FC7
|
|||
|
DB (FCBSIZ - 2) DUP (-1)
|
|||
|
FC7 DW OFFSET DG:FC8
|
|||
|
DB (FCBSIZ - 2) DUP (-1)
|
|||
|
FC8 DW OFFSET DG:FC9
|
|||
|
DB (FCBSIZ - 2) DUP (-1)
|
|||
|
FC9 DW OFFSET DG:SPLFCB
|
|||
|
DB (FCBSIZ - 2) DUP (-1)
|
|||
|
|
|||
|
DEF_ENDRES LABEL BYTE
|
|||
|
|
|||
|
ASSUME CS:DG,DS:DG,ES:DG,SS:DG
|
|||
|
|
|||
|
BADSPOOL:
|
|||
|
MOV DX,OFFSET DG:BADMES
|
|||
|
MOV AH,STD_CON_STRING_OUTPUT
|
|||
|
INT 21H
|
|||
|
INT 20H
|
|||
|
|
|||
|
SETUP:
|
|||
|
;Called once to install resident
|
|||
|
CLD
|
|||
|
MOV [INTSEG],CS
|
|||
|
MOV DX,OFFSET DG:PROMPT
|
|||
|
MOV AH,STD_CON_STRING_OUTPUT
|
|||
|
INT 21H
|
|||
|
MOV DX,OFFSET DG:COMBUF
|
|||
|
MOV AH,STD_CON_STRING_INPUT
|
|||
|
INT 21H ;Get device name
|
|||
|
MOV DX,OFFSET DG:CRLF
|
|||
|
MOV AH,STD_CON_STRING_OUTPUT
|
|||
|
INT 21H
|
|||
|
MOV CL,[COMBUF+1]
|
|||
|
OR CL,CL
|
|||
|
JZ DEFSPOOL ;User didn't specify one
|
|||
|
XOR CH,CH
|
|||
|
MOV DI,OFFSET DG:LISTFCB + 1
|
|||
|
MOV SI,OFFSET DG:COMBUF + 2
|
|||
|
REP MOVSB
|
|||
|
DEFSPOOL:
|
|||
|
MOV DX,OFFSET DG:LISTFCB
|
|||
|
MOV AH,FCB_OPEN
|
|||
|
INT 21H
|
|||
|
OR AL,AL
|
|||
|
JNZ BADSPOOL ;Bad
|
|||
|
TEST BYTE PTR [LISTFCB.fcb_DEVID],080H
|
|||
|
JZ BADSPOOL ;Must be a device
|
|||
|
LDS SI,DWORD PTR [LISTFCB.fcb_FIRCLUS]
|
|||
|
ASSUME DS:NOTHING
|
|||
|
MOV WORD PTR [CALLAD+2],DS ;Get I/O routines
|
|||
|
MOV WORD PTR [LISTDEV+2],DS ;Get I/O routines
|
|||
|
MOV WORD PTR [LISTDEV],SI
|
|||
|
PUSH CS
|
|||
|
POP DS
|
|||
|
ASSUME DS:DG
|
|||
|
MOV DX,OFFSET DG:SPINT
|
|||
|
MOV AL,SOFTINT
|
|||
|
MOV AH,GET_INTERRUPT_VECTOR
|
|||
|
INT 21H ;Get soft vector
|
|||
|
MOV WORD PTR [SPNEXT+2],ES
|
|||
|
MOV WORD PTR [SPNEXT],BX
|
|||
|
MOV AL,SOFTINT
|
|||
|
MOV AH,SET_INTERRUPT_VECTOR
|
|||
|
INT 21H ;Set soft vector
|
|||
|
MOV DX,OFFSET DG:SPCOMINT
|
|||
|
MOV AL,COMINT
|
|||
|
MOV AH,SET_INTERRUPT_VECTOR ;Set communication vector
|
|||
|
INT 21H
|
|||
|
|
|||
|
IF IBM
|
|||
|
MOV AL,13H
|
|||
|
MOV AH,GET_INTERRUPT_VECTOR
|
|||
|
INT 21H
|
|||
|
MOV WORD PTR [REAL_INT_13+2],ES
|
|||
|
MOV WORD PTR [REAL_INT_13],BX
|
|||
|
MOV DX,OFFSET DG:INT_13
|
|||
|
MOV AL,13H
|
|||
|
MOV AH,SET_INTERRUPT_VECTOR
|
|||
|
INT 21H ;Set diskI/O interrupt
|
|||
|
MOV AL,17H
|
|||
|
MOV AH,GET_INTERRUPT_VECTOR
|
|||
|
INT 21H
|
|||
|
MOV WORD PTR [REAL_INT_17+2],ES
|
|||
|
MOV WORD PTR [REAL_INT_17],BX
|
|||
|
MOV AL,14H
|
|||
|
MOV AH,GET_INTERRUPT_VECTOR
|
|||
|
INT 21H
|
|||
|
MOV WORD PTR [REAL_INT_14+2],ES
|
|||
|
MOV WORD PTR [REAL_INT_14],BX
|
|||
|
MOV AL,5H
|
|||
|
MOV AH,GET_INTERRUPT_VECTOR
|
|||
|
INT 21H
|
|||
|
MOV WORD PTR [REAL_INT_5+2],ES
|
|||
|
MOV WORD PTR [REAL_INT_5],BX
|
|||
|
PUSH CS
|
|||
|
POP ES
|
|||
|
MOV BP,OFFSET DG:LISTFCB + 1
|
|||
|
MOV SI,BP
|
|||
|
MOV CX,8
|
|||
|
CONLP: ;Make sure device name in upper case
|
|||
|
LODSB
|
|||
|
CMP AL,'a'
|
|||
|
JB DOCONLP
|
|||
|
CMP AL,'z'
|
|||
|
JA DOCONLP
|
|||
|
SUB BYTE PTR [SI-1],20H
|
|||
|
DOCONLP:
|
|||
|
LOOP CONLP
|
|||
|
MOV DI,OFFSET DG:INT_17_HITLIST
|
|||
|
CHKHIT:
|
|||
|
MOV SI,BP
|
|||
|
MOV CL,[DI]
|
|||
|
INC DI
|
|||
|
JCXZ NOTONHITLIST
|
|||
|
REPE CMPSB
|
|||
|
LAHF
|
|||
|
ADD DI,CX ;Bump to next position without affecting flags
|
|||
|
MOV BL,[DI] ;Get device number
|
|||
|
INC DI
|
|||
|
SAHF
|
|||
|
JNZ CHKHIT
|
|||
|
XOR BH,BH
|
|||
|
MOV [INT_17_NUM],BX
|
|||
|
MOV DX,OFFSET DG:INT_17
|
|||
|
MOV AL,17H
|
|||
|
MOV AH,SET_INTERRUPT_VECTOR
|
|||
|
INT 21H ;Set printer interrupt
|
|||
|
MOV DX,OFFSET DG:INT_5
|
|||
|
MOV AL,5H
|
|||
|
MOV AH,SET_INTERRUPT_VECTOR
|
|||
|
INT 21H ;Set print screen interrupt
|
|||
|
JMP SHORT ALLSET
|
|||
|
NOTONHITLIST:
|
|||
|
MOV DI,OFFSET DG:INT_14_HITLIST
|
|||
|
CHKHIT2:
|
|||
|
MOV SI,BP
|
|||
|
MOV CL,[DI]
|
|||
|
INC DI
|
|||
|
JCXZ ALLSET
|
|||
|
REPE CMPSB
|
|||
|
LAHF
|
|||
|
ADD DI,CX ;Bump to next position without affecting flags
|
|||
|
MOV BL,[DI] ;Get device number
|
|||
|
INC DI
|
|||
|
SAHF
|
|||
|
JNZ CHKHIT2
|
|||
|
XOR BH,BH
|
|||
|
MOV [INT_14_NUM],BX
|
|||
|
MOV DX,OFFSET DG:INT_14
|
|||
|
MOV AL,14H
|
|||
|
MOV AH,SET_INTERRUPT_VECTOR
|
|||
|
INT 21H ;Set RS232 port interrupt
|
|||
|
ALLSET:
|
|||
|
ENDIF
|
|||
|
|
|||
|
IF HARDINT
|
|||
|
MOV AH,GET_INDOS_FLAG
|
|||
|
INT 21H
|
|||
|
MOV WORD PTR [INDOS+2],ES ;Get indos flag location
|
|||
|
MOV WORD PTR [INDOS],BX
|
|||
|
MOV AL,INTLOC
|
|||
|
MOV AH,GET_INTERRUPT_VECTOR
|
|||
|
INT 21H
|
|||
|
MOV WORD PTR [NEXTINT+2],ES
|
|||
|
MOV WORD PTR [NEXTINT],BX
|
|||
|
MOV DX,OFFSET DG:HDSPINT
|
|||
|
MOV AL,INTLOC
|
|||
|
MOV AH,SET_INTERRUPT_VECTOR
|
|||
|
INT 21H ;Set hardware interrupt
|
|||
|
ENDIF
|
|||
|
|
|||
|
MOV [MAKERES],1 ;Indicate to do a terminate stay resident
|
|||
|
MOV DX,OFFSET DG:GOODMES
|
|||
|
MOV AH,STD_CON_STRING_OUTPUT
|
|||
|
INT 21H
|
|||
|
RET
|
|||
|
|
|||
|
ASSUME CS:DG,DS:DG,ES:DG,SS:DG
|
|||
|
|
|||
|
TRANSIENT:
|
|||
|
;User interface
|
|||
|
CLD
|
|||
|
|
|||
|
;Code to print header
|
|||
|
; MOV DX,OFFSET DG:HEADER
|
|||
|
; MOV AH,STD_CON_STRING_OUTPUT
|
|||
|
; INT 21H
|
|||
|
|
|||
|
DOSVER_LOW EQU 0136H ;1.54 in hex
|
|||
|
DOSVER_HIGH EQU 020BH ;2.11 in hex
|
|||
|
MOV AH,GET_VERSION
|
|||
|
INT 21H
|
|||
|
XCHG AH,AL ;Turn it around to AH.AL
|
|||
|
CMP AX,DOSVER_LOW
|
|||
|
JB GOTBADDOS
|
|||
|
CMP AX,DOSVER_HIGH
|
|||
|
JBE OKDOS
|
|||
|
GOTBADDOS:
|
|||
|
PUSH CS
|
|||
|
POP DS
|
|||
|
MOV DX,OFFSET DG:BADVER
|
|||
|
MOV AH,STD_CON_STRING_OUTPUT
|
|||
|
INT 21H
|
|||
|
INT 20H
|
|||
|
OKDOS:
|
|||
|
MOV AX,CHAR_OPER SHL 8
|
|||
|
INT 21H
|
|||
|
MOV [SWITCHAR],DL ;Get user switch character
|
|||
|
MOV AH,GET_INTERRUPT_VECTOR
|
|||
|
MOV AL,COMINT
|
|||
|
INT 21H
|
|||
|
ASSUME ES:NOTHING
|
|||
|
MOV DI,BX
|
|||
|
MOV SI,OFFSET DG:SPCOMINT
|
|||
|
MOV CX,13
|
|||
|
REPE CMPSB
|
|||
|
JZ GOTRES ;Signature matched
|
|||
|
PUSH CS
|
|||
|
POP ES
|
|||
|
CALL SETUP
|
|||
|
GOTRES:
|
|||
|
PUSH CS
|
|||
|
POP ES
|
|||
|
MOV AH,GET_DEFAULT_DRIVE
|
|||
|
INT 21H
|
|||
|
MOV [DEFDRV],AL
|
|||
|
MOV SI,PARMS
|
|||
|
LODSB
|
|||
|
OR AL,AL
|
|||
|
JNZ GOTPARMS
|
|||
|
TRANEXIT:
|
|||
|
CALL GETSPLIST
|
|||
|
CMP [MAKERES],0
|
|||
|
JNZ SETRES
|
|||
|
INT 20H
|
|||
|
|
|||
|
SETRES:
|
|||
|
MOV DX,[ENDRES]
|
|||
|
INT 27H
|
|||
|
|
|||
|
ARGSDONE:
|
|||
|
CMP [ARGSETUP],0
|
|||
|
JZ TRANEXIT
|
|||
|
CALL PROCESS
|
|||
|
JMP SHORT TRANEXIT
|
|||
|
|
|||
|
GOTPARMS:
|
|||
|
PARSE:
|
|||
|
MOV DI,OFFSET DG:PARSEBUF
|
|||
|
CALL CPARSE
|
|||
|
JC ARGSDONE
|
|||
|
CMP AX,4 ;Switch?
|
|||
|
JNZ GOTNORMARG
|
|||
|
MOV AL,[DI] ;Get the switch character
|
|||
|
CMP AL,'C'
|
|||
|
JZ SETCAN
|
|||
|
CMP AL,'c'
|
|||
|
JNZ CHKSPL
|
|||
|
SETCAN:
|
|||
|
MOV [CANFLG],1
|
|||
|
JMP SHORT PARSE
|
|||
|
CHKSPL:
|
|||
|
CMP AL,'P'
|
|||
|
JZ RESETCAN
|
|||
|
CMP AL,'p'
|
|||
|
JNZ CHKTERM
|
|||
|
RESETCAN:
|
|||
|
MOV [CANFLG],0
|
|||
|
JMP SHORT PARSE
|
|||
|
CHKTERM:
|
|||
|
CMP AL,'T'
|
|||
|
JZ SETTERM
|
|||
|
CMP AL,'t'
|
|||
|
JZ SETTERM
|
|||
|
MOV DX,OFFSET DG:BADSWT
|
|||
|
MOV AH,STD_CON_STRING_OUTPUT
|
|||
|
INT 21H
|
|||
|
JMP SHORT PARSE
|
|||
|
|
|||
|
SETTERM:
|
|||
|
CALL TERMPROCESS
|
|||
|
JMP TRANEXIT ; Ignore everything after T switch
|
|||
|
|
|||
|
GOTNORMARG:
|
|||
|
XOR AL,AL
|
|||
|
XCHG AL,[ARGSETUP]
|
|||
|
OR AL,AL
|
|||
|
JZ PARSEARG
|
|||
|
CALL NORMPROC ;Don't test ARGSETUP, it just got zeroed
|
|||
|
PARSEARG:
|
|||
|
PUSH SI
|
|||
|
MOV SI,DI
|
|||
|
MOV DI,FCB
|
|||
|
MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 1
|
|||
|
INT 21H ;Parse the arg
|
|||
|
CMP BYTE PTR [DI],0
|
|||
|
JNZ DRVOK
|
|||
|
MOV DL,[DEFDRV]
|
|||
|
INC DL
|
|||
|
MOV BYTE PTR [DI],DL ;Set the default drive
|
|||
|
DRVOK:
|
|||
|
POP SI
|
|||
|
INC [ARGSETUP]
|
|||
|
JMP SHORT PARSE
|
|||
|
|
|||
|
TERMPROCESS:
|
|||
|
MOV DX,-1
|
|||
|
PROCRET:
|
|||
|
MOV AH,1
|
|||
|
CALL DOSET
|
|||
|
PROCRETNFUNC:
|
|||
|
MOV [ARGSETUP],0
|
|||
|
PUSH CS
|
|||
|
POP ES
|
|||
|
RET14: RET
|
|||
|
|
|||
|
PROCESS:
|
|||
|
CMP [ARGSETUP],0
|
|||
|
JZ RET14 ;Nothing to process
|
|||
|
NORMPROC:
|
|||
|
MOV AL,BYTE PTR DS:[FCB+1]
|
|||
|
CMP AL," "
|
|||
|
JZ SRCHBADJ
|
|||
|
MOV DX,FCB
|
|||
|
MOV AH,[CANFLG]
|
|||
|
CMP AH,0
|
|||
|
JNZ PROCRET
|
|||
|
MOV DX,OFFSET DG:SRCHFCB
|
|||
|
MOV AH,SET_DMA
|
|||
|
INT 21H
|
|||
|
MOV DX,FCB
|
|||
|
MOV AH,DIR_SEARCH_FIRST
|
|||
|
INT 21H
|
|||
|
OR AL,AL
|
|||
|
JNZ SRCHBADJ
|
|||
|
SRCHLOOP:
|
|||
|
MOV DX,OFFSET DG:SRCHFCB
|
|||
|
MOV AH,FCB_OPEN
|
|||
|
INT 21H
|
|||
|
OR AL,AL
|
|||
|
JZ OPENOK
|
|||
|
CALL OPENERR
|
|||
|
JMP SHORT NEXTSEARCH
|
|||
|
SRCHBADJ: JMP SRCHBAD
|
|||
|
OPENOK:
|
|||
|
MOV DX,OFFSET DG:SRCHFCB
|
|||
|
MOV AH,0
|
|||
|
CALL DOSET
|
|||
|
OR AL,AL
|
|||
|
JZ NEXTSEARCH
|
|||
|
XCHG AL,[FULLFLAG] ;Know AL non-zero
|
|||
|
OR AL,AL
|
|||
|
JNZ NEXTSEARCH ;Only print message once
|
|||
|
MOV DX,OFFSET DG:FULLMES ;Queue full
|
|||
|
MOV AH,STD_CON_STRING_OUTPUT
|
|||
|
INT 21H
|
|||
|
NEXTSEARCH:
|
|||
|
MOV DX,OFFSET DG:SRCHFCB
|
|||
|
MOV AH,SET_DMA
|
|||
|
INT 21H
|
|||
|
MOV DX,FCB
|
|||
|
MOV AH,DIR_SEARCH_NEXT
|
|||
|
INT 21H
|
|||
|
OR AL,AL
|
|||
|
JNZ PROCRETNFUNC
|
|||
|
JMP SRCHLOOP
|
|||
|
|
|||
|
DOSET:
|
|||
|
INT COMINT
|
|||
|
MOV [FILCNT],AH ;Suck up return info
|
|||
|
MOV WORD PTR [SPLIST+2],ES
|
|||
|
MOV WORD PTR [CURFILE+2],ES
|
|||
|
MOV WORD PTR [SPLIST],BX
|
|||
|
MOV WORD PTR [CURFILE],DX
|
|||
|
RET
|
|||
|
|
|||
|
OPENERR:
|
|||
|
PUSH SI
|
|||
|
PUSH DI
|
|||
|
MOV SI,OFFSET DG:OPFILNAM
|
|||
|
PUSH DS
|
|||
|
POP ES
|
|||
|
MOV DI,OFFSET DG:SRCHFCB
|
|||
|
CALL MVFNAM
|
|||
|
MOV DX,OFFSET DG:OPMES
|
|||
|
MOV AH,STD_CON_STRING_OUTPUT
|
|||
|
INT 21H
|
|||
|
POP DI
|
|||
|
POP SI
|
|||
|
RET
|
|||
|
|
|||
|
SRCHBAD:
|
|||
|
PUSH SI
|
|||
|
PUSH DI
|
|||
|
MOV SI,OFFSET DG:SRCHFNAM
|
|||
|
PUSH DS
|
|||
|
POP ES
|
|||
|
MOV DI,FCB
|
|||
|
CALL MVFNAM
|
|||
|
MOV DX,OFFSET DG:SRCHMES
|
|||
|
MOV AH,STD_CON_STRING_OUTPUT
|
|||
|
INT 21H
|
|||
|
POP DI
|
|||
|
POP SI
|
|||
|
JMP PROCRETNFUNC
|
|||
|
|
|||
|
GETSPLIST:
|
|||
|
MOV AH,0FFH
|
|||
|
CALL DOSET
|
|||
|
PUSH DS
|
|||
|
LDS DI,[SPLIST]
|
|||
|
MOV DI,[DI-2] ;Get the error count
|
|||
|
POP DS
|
|||
|
CMP DI,ERRCNT1
|
|||
|
JB CNTOK
|
|||
|
MOV DX,OFFSET DG:CNTMES
|
|||
|
MOV AH,STD_CON_STRING_OUTPUT
|
|||
|
INT 21H
|
|||
|
CNTOK:
|
|||
|
MOV CL,[FILCNT]
|
|||
|
OR CL,CL
|
|||
|
JZ NOFILES
|
|||
|
XOR CH,CH
|
|||
|
LES DI,[CURFILE]
|
|||
|
PUSH DI
|
|||
|
INC DI
|
|||
|
INC DI
|
|||
|
MOV SI,OFFSET DG:CURFNAM
|
|||
|
CALL MVFNAM
|
|||
|
POP DI
|
|||
|
MOV DX,OFFSET DG:CURMES
|
|||
|
MOV AH,STD_CON_STRING_OUTPUT
|
|||
|
INT 21H
|
|||
|
DEC CX
|
|||
|
JCXZ RET12
|
|||
|
FILOOP:
|
|||
|
MOV DI,ES:[DI]
|
|||
|
PUSH DI
|
|||
|
INC DI
|
|||
|
INC DI
|
|||
|
MOV SI,OFFSET DG:FILFNAM
|
|||
|
CALL MVFNAM
|
|||
|
POP DI
|
|||
|
MOV DX,OFFSET DG:FILMES
|
|||
|
MOV AH,STD_CON_STRING_OUTPUT
|
|||
|
INT 21H
|
|||
|
LOOP FILOOP
|
|||
|
RET12: RET
|
|||
|
|
|||
|
NOFILES:
|
|||
|
MOV DX,OFFSET DG:NOFILS
|
|||
|
MOV AH,STD_CON_STRING_OUTPUT
|
|||
|
INT 21H
|
|||
|
RET
|
|||
|
|
|||
|
;Make a message with the file name
|
|||
|
MVFNAM:
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING
|
|||
|
PUSH SI
|
|||
|
PUSH DI
|
|||
|
PUSH CX
|
|||
|
MOV AX,ES
|
|||
|
PUSH DS
|
|||
|
POP ES
|
|||
|
MOV DS,AX
|
|||
|
XCHG SI,DI
|
|||
|
LODSB
|
|||
|
ADD AL,"@"
|
|||
|
CMP AL,"@"
|
|||
|
JNZ STCHR
|
|||
|
MOV AL,[DEFDRV]
|
|||
|
ADD AL,"A"
|
|||
|
STCHR:
|
|||
|
STOSB
|
|||
|
INC DI
|
|||
|
MOV CX,4
|
|||
|
REP MOVSW
|
|||
|
INC DI
|
|||
|
MOVSW
|
|||
|
MOVSB
|
|||
|
MOV AX,ES
|
|||
|
PUSH DS
|
|||
|
POP ES
|
|||
|
MOV DS,AX
|
|||
|
POP CX
|
|||
|
POP DI
|
|||
|
POP SI
|
|||
|
RET
|
|||
|
|
|||
|
;-----------------------------------------------------------------------;
|
|||
|
; ENTRY: ;
|
|||
|
; DS:SI Points input buffer ;
|
|||
|
; ES:DI Points to the token buffer ;
|
|||
|
; ;
|
|||
|
; EXIT: ;
|
|||
|
; DS:SI Points to next char in the input buffer ;
|
|||
|
; ES:DI Points to the token buffer ;
|
|||
|
; CX Character count ;
|
|||
|
; AX Condition Code ;
|
|||
|
; =1 same as carry set ;
|
|||
|
; =2 normal token ;
|
|||
|
; =4 switch character, char in token buffer ;
|
|||
|
; Carry Flag Set if a CR was found, Reset otherwise ;
|
|||
|
; ;
|
|||
|
; MODIFIES: ;
|
|||
|
; CX, SI, AX and the Carry Flag ;
|
|||
|
; ;
|
|||
|
;-----------------------------------------------------------------------;
|
|||
|
|
|||
|
TAB equ 09h
|
|||
|
CR equ 0dh
|
|||
|
|
|||
|
CPARSE:
|
|||
|
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
|
|||
|
pushf ;save flags
|
|||
|
push di ;save the token buffer addrss
|
|||
|
xor cx,cx ;no chars in token buffer
|
|||
|
call kill_bl
|
|||
|
|
|||
|
cmp al,CR ;a CR?
|
|||
|
jne sj2 ;no, skip
|
|||
|
sj1:
|
|||
|
mov ax,1 ;condition code
|
|||
|
dec si ;adjust the pointer
|
|||
|
pop di ;retrive token buffer address
|
|||
|
popf ;restore flags
|
|||
|
stc ;set the carry bit
|
|||
|
ret
|
|||
|
|
|||
|
sj2:
|
|||
|
mov dl,[SWITCHAR]
|
|||
|
cmp al,dl ;is the char the switch char?
|
|||
|
jne anum_char ;no, process...
|
|||
|
call kill_bl
|
|||
|
cmp al,CR ;a CR?
|
|||
|
je sj1 ;yes, error exit
|
|||
|
call move_char ;Put the switch char in the token buffer
|
|||
|
mov ax,4 ;Flag switch
|
|||
|
jmp short x_done2
|
|||
|
|
|||
|
anum_char:
|
|||
|
call move_char ;just an alphanum string
|
|||
|
lodsb
|
|||
|
cmp al,' '
|
|||
|
je x_done
|
|||
|
cmp al,tab
|
|||
|
je x_done
|
|||
|
cmp al,CR
|
|||
|
je x_done
|
|||
|
cmp al,','
|
|||
|
je x_done
|
|||
|
cmp al,'='
|
|||
|
je x_done
|
|||
|
cmp al,dl ;Switch character
|
|||
|
jne anum_char
|
|||
|
x_done:
|
|||
|
dec si ;adjust for next round
|
|||
|
mov ax,2 ;normal token
|
|||
|
x_done2:
|
|||
|
push ax ;save condition code
|
|||
|
mov al,0
|
|||
|
stosb ;null at the end
|
|||
|
pop ax
|
|||
|
pop di ;restore token buffer pointer
|
|||
|
popf
|
|||
|
clc ;clear carry flag
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
kill_bl proc near
|
|||
|
lodsb
|
|||
|
cmp al,' '
|
|||
|
je kill_bl
|
|||
|
cmp al,tab
|
|||
|
je kill_bl
|
|||
|
cmp al,',' ;a comma?
|
|||
|
je kill_bl
|
|||
|
cmp al,'='
|
|||
|
je kill_bl
|
|||
|
ret
|
|||
|
kill_bl endp
|
|||
|
|
|||
|
|
|||
|
move_char proc near
|
|||
|
stosb ;store char in token buffer
|
|||
|
inc cx ;increment char count
|
|||
|
ret
|
|||
|
move_char endp
|
|||
|
|
|||
|
CODE ENDS
|
|||
|
END START
|
|||
|
|