Added the reconstructed source code of RDCPM.COM and EDLIN.COM, and changed the style of the other source files to match Tim Paterson's coding style.
680 lines
9.0 KiB
NASM
680 lines
9.0 KiB
NASM
FCB EQU 5CH
|
|
RENAM EQU 23
|
|
OPEN EQU 15
|
|
CLOSE EQU 16
|
|
MAKE EQU 22
|
|
DELFIL EQU 19
|
|
RDBLK EQU 39
|
|
WRBLK EQU 40
|
|
SETDMA EQU 26
|
|
PRINTBUF EQU 9
|
|
OUTCH EQU 2
|
|
INBUF EQU 10
|
|
RR EQU 33
|
|
|
|
PROMPT EQU "*"
|
|
|
|
ORG 100H
|
|
|
|
MOV SP,STACK
|
|
MOV DX,BREAK
|
|
MOV AX,2523H
|
|
INT 21H
|
|
MOV SI,BAK
|
|
MOV DI,FCB+9
|
|
MOV CX,3
|
|
;File must not have .BAK extension
|
|
REPE
|
|
CMPB
|
|
JZ NOTBAK
|
|
;Open input file
|
|
MOV AH,OPEN
|
|
MOV DX,FCB
|
|
INT 21H
|
|
MOV [HAVEOF],AL
|
|
OR AL,AL
|
|
JZ HAVFIL
|
|
MOV DX,NEWFIL
|
|
MOV AH,PRINTBUF
|
|
INT 21H
|
|
HAVFIL:
|
|
MOV SI,FCB
|
|
MOV DI,FCB2
|
|
MOV CX,9
|
|
REP
|
|
MOVB
|
|
MOV SI,BAK
|
|
MOVW
|
|
MOVB
|
|
MOV AH,DELFIL
|
|
MOV DX,FCB2
|
|
INT 21H
|
|
MOV AL,"$"
|
|
MOV DI,FCB2+9
|
|
STOB
|
|
STOB
|
|
STOB
|
|
MOV AH,DELFIL
|
|
INT 21H
|
|
;Create .$$$ file to make sure directory has room
|
|
MOV AH,MAKE
|
|
INT 21H
|
|
OR AL,AL
|
|
JZ SETUP
|
|
MOV DX,NODIR
|
|
JMP ERROR
|
|
NOTBAK:
|
|
MOV DX,NOBAK
|
|
JMP ERROR
|
|
TOOBIG:
|
|
MOV DX,TOBIG
|
|
JMP ERROR
|
|
NOTEOF:
|
|
MOV DX,NOEOF
|
|
JMP ERROR
|
|
SETUP:
|
|
MOV DX,START
|
|
MOV AH,SETDMA
|
|
INT 21H
|
|
MOV CX,[6]
|
|
SUB CX,80H
|
|
MOV [LAST],CX
|
|
MOV DI,START-1
|
|
TEST B,[HAVEOF],-1
|
|
JNZ SAVEND
|
|
CALL NUMRECS
|
|
MOV [FCB+RR],0
|
|
MOV DX,FCB
|
|
MOV AH,RDBLK
|
|
INT 21H
|
|
CMP AL,2
|
|
JZ TOOBIG
|
|
JCXZ SAVEND
|
|
ROR CX
|
|
XCHG CL,CH
|
|
ADD DI,CX ;Point to last byte
|
|
DOWN
|
|
MOV AL,1AH
|
|
REPNE
|
|
SCAB
|
|
JNZ NOTEOF
|
|
REPE
|
|
SCAB
|
|
INC DI
|
|
SAVEND:
|
|
CLD
|
|
INC DI
|
|
MOV B,[DI],1AH
|
|
MOV [ENDTXT],DI
|
|
MOV B,[COMBUF],128
|
|
MOV B,[EDITBUF],255
|
|
MOV [POINTER],START
|
|
MOV [CURRENT],1
|
|
|
|
COMMAND:
|
|
MOV SP,STACK
|
|
MOV AL,PROMPT
|
|
CALL OUT
|
|
MOV DX,COMBUF
|
|
MOV AH,INBUF
|
|
INT 21H
|
|
MOV AL,10
|
|
CALL OUT
|
|
MOV [PARAM2],0
|
|
MOV B,[QFLG],0
|
|
MOV SI,2+COMBUF
|
|
CALL GETNUM
|
|
MOV [PARAM1],DX
|
|
CALL SKIP1
|
|
CMP AL,","
|
|
JNZ CHKNXT
|
|
INC SI
|
|
CHKNXT:
|
|
DEC SI
|
|
CALL GETNUM
|
|
MOV [PARAM2],DX
|
|
CALL SKIP1
|
|
CMP AL,"?"
|
|
JNZ DISPATCH
|
|
MOV [QFLG],AL
|
|
CALL SKIP
|
|
DISPATCH:
|
|
AND AL,5FH
|
|
MOV DI,COMTAB
|
|
MOV CX,NUMCOM
|
|
REPNE
|
|
SCAB
|
|
JNZ COMERR
|
|
MOV BX,CX
|
|
SHL BX
|
|
CALL [BX+TABLE]
|
|
JMP COMMAND
|
|
|
|
SKIP:
|
|
LODB
|
|
SKIP1:
|
|
CMP AL," "
|
|
JZ SKIP
|
|
RET
|
|
|
|
COMERR:
|
|
MOV DX,BADCOM
|
|
MOV AH,PRINTBUF
|
|
INT 21H
|
|
JP COMMAND
|
|
|
|
|
|
GETNUM:
|
|
CALL SKIP
|
|
CMP AL,"."
|
|
JZ CURLIN
|
|
CMP AL,"#"
|
|
JZ MAXLIN
|
|
MOV DX,0
|
|
NUMLP:
|
|
CMP AL,"0"
|
|
JB RET
|
|
CMP AL,"9"
|
|
JA RET
|
|
SUB AL,"0"
|
|
MOV BX,DX
|
|
SHL DX
|
|
SHL DX
|
|
ADD DX,BX
|
|
SHL DX
|
|
CBW
|
|
ADD DX,AX
|
|
LODB
|
|
JP NUMLP
|
|
|
|
CURLIN:
|
|
MOV DX,[CURRENT]
|
|
LODB
|
|
RET
|
|
MAXLIN:
|
|
MOV DX,-1
|
|
LODB
|
|
RET
|
|
|
|
|
|
COMTAB DB "SFDLIE",13
|
|
|
|
NUMCOM EQU $-COMTAB
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Carefull changing the order of the next two tables. They are
|
|
; linked and chnges should be be to both.
|
|
|
|
TABLE DW NOCOM ;No command--edit line
|
|
DW ENDED
|
|
DW INSERT
|
|
DW LIST
|
|
DW DELETE
|
|
DW COMERR
|
|
DW COMERR
|
|
|
|
FINDLIN:
|
|
|
|
; Inputs
|
|
; BX = Line number to be located in buffer (0 means last line)
|
|
; Outputs:
|
|
; DX = Actual line found
|
|
; DI = Pointer to start of line DX
|
|
; Zero set if BX = DX
|
|
; AL,CX destroyed. No other registers affected.
|
|
|
|
MOV DX,[CURRENT]
|
|
MOV DI,[POINTER]
|
|
CMP BX,DX
|
|
JZ RET
|
|
JA FINDIT
|
|
MOV DX,1
|
|
MOV DI,START
|
|
CMP BX,DX
|
|
JZ RET
|
|
FINDIT:
|
|
MOV CX,[ENDTXT]
|
|
SUB CX,DI
|
|
MOV AL,10
|
|
OR AL,AL ;Clear zero flag
|
|
FINLIN:
|
|
JCXZ RET
|
|
REPNE
|
|
SCAB
|
|
INC DX
|
|
CMP BX,DX
|
|
JNZ FINLIN
|
|
RET
|
|
|
|
|
|
SHOWNUM:
|
|
|
|
; Inputs:
|
|
; BX = Line number to be displayed
|
|
; Function:
|
|
; Displays line number on terminal in 8-character
|
|
; format, suppressing leading zeros.
|
|
; AX, CX, DX destroyed. No other registers affected.
|
|
|
|
PUSH BX
|
|
MOV AL," "
|
|
CALL OUT
|
|
CALL CONV10
|
|
MOV AL,":"
|
|
CALL OUT
|
|
MOV AL," "
|
|
CALL OUT
|
|
POP BX
|
|
RET
|
|
|
|
|
|
CONV10:
|
|
|
|
;Inputs:
|
|
; BX = Binary number to be displayed
|
|
; Function:
|
|
; Ouputs binary number. Five digits with leading
|
|
; zero suppression. Zero prints 5 blanks.
|
|
|
|
XOR AX,AX
|
|
MOV DL,AL
|
|
MOV CX,16
|
|
CONV:
|
|
SHL BX
|
|
ADC AL,AL
|
|
DAA
|
|
XCHG AL,AH
|
|
ADC AL,AL
|
|
DAA
|
|
XCHG AL,AH
|
|
ADC DL,DL
|
|
LOOP CONV
|
|
MOV BL,"0"-" "
|
|
XCHG AX,DX
|
|
CALL LDIG
|
|
MOV AL,DH
|
|
CALL DIGITS
|
|
MOV AL,DL
|
|
DIGITS:
|
|
MOV DH,AL
|
|
SHR AL
|
|
SHR AL
|
|
SHR AL
|
|
SHR AL
|
|
CALL LDIG
|
|
MOV AL,DH
|
|
LDIG:
|
|
AND AL,0FH
|
|
JZ ZERDIG
|
|
MOV BL,0
|
|
ZERDIG:
|
|
ADD AL,"0"
|
|
SUB AL,BL
|
|
JMP OUT
|
|
|
|
|
|
LIST:
|
|
MOV BX,[PARAM1]
|
|
OR BX,BX
|
|
JNZ CHKP2
|
|
MOV BX,[CURRENT]
|
|
SUB BX,10
|
|
JA CHKP2
|
|
MOV BX,1
|
|
CHKP2:
|
|
CALL FINDLIN
|
|
JNZ RET
|
|
MOV SI,DI
|
|
MOV DI,[PARAM2]
|
|
INC DI
|
|
SUB DI,BX
|
|
JA DISPLAY
|
|
MOV DI,21
|
|
JP DISPLAY
|
|
|
|
|
|
DISPONE:
|
|
MOV DI,1
|
|
|
|
DISPLAY:
|
|
|
|
; Inputs:
|
|
; BX = Line number
|
|
; SI = Pointer to text buffer
|
|
; DI = No. of lines
|
|
; Function:
|
|
; Ouputs specified no. of line to terminal, each
|
|
; with leading line number.
|
|
; Outputs:
|
|
; BX = Last line output.
|
|
; All registers destroyed.
|
|
|
|
MOV CX,[ENDTXT]
|
|
SUB CX,SI
|
|
JZ RET
|
|
MOV BP,[CURRENT]
|
|
DISPLN:
|
|
PUSH CX
|
|
CALL SHOWNUM
|
|
POP CX
|
|
OUTLN:
|
|
LODB
|
|
CALL OUT
|
|
CMP AL,10
|
|
LOOPNZ OUTLN
|
|
JCXZ RET
|
|
DEC DI
|
|
JZ RET
|
|
CMP BX,BP
|
|
LAHF
|
|
INC BX
|
|
SAHF
|
|
JZ OUTLF
|
|
CMP BX,BP
|
|
JNZ DISPLN
|
|
OUTLF:
|
|
MOV AL,10
|
|
CALL OUT
|
|
JP DISPLN
|
|
RET: RET
|
|
|
|
|
|
NOCOM:
|
|
MOV BX,[PARAM1]
|
|
OR BX,BX
|
|
JNZ HAVLIN
|
|
MOV BX,[CURRENT]
|
|
INC BX ;Default is current line plus one
|
|
HAVLIN:
|
|
CALL FINDLIN
|
|
MOV SI,DI
|
|
MOV [CURRENT],DX
|
|
MOV [POINTER],SI
|
|
JNZ RET
|
|
CMP SI,[ENDTXT]
|
|
JZ RET
|
|
MOV DI,2+EDITBUF
|
|
MOV CX,254
|
|
MOV DL,-1
|
|
LOADLP:
|
|
LODB
|
|
STOB
|
|
INC DL
|
|
CMP AL,13
|
|
LOOPNZ LOADLP
|
|
MOV [EDITBUF+1],DL
|
|
MOV [OLDLEN],DL
|
|
MOV SI,[POINTER]
|
|
CALL DISPONE
|
|
CALL SHOWNUM
|
|
MOV AH,INBUF ;Get input buffer
|
|
MOV DX,EDITBUF
|
|
INT 21H
|
|
MOV AL,10
|
|
CALL OUT
|
|
MOV CL,[EDITBUF+1]
|
|
MOV CH,0
|
|
JCXZ RET
|
|
MOV DL,[OLDLEN]
|
|
MOV DH,0
|
|
MOV SI,2+EDITBUF
|
|
MOV DI,[POINTER]
|
|
|
|
REPLACE:
|
|
|
|
; Inputs:
|
|
; CX = Length of new text
|
|
; DX = Length of original text
|
|
; SI = Pointer to new text
|
|
; DI = Pointer to old text in buffer
|
|
; Function:
|
|
; New text replaces old text in buffer and buffer
|
|
; size is adjusted. CX or DX may be zero.
|
|
; CX, SI, DI all destroyed. No other registers affected.
|
|
|
|
CMP CX,DX
|
|
JZ COPYIN
|
|
PUSH SI
|
|
PUSH DI
|
|
PUSH CX
|
|
MOV SI,DI
|
|
ADD SI,DX
|
|
ADD DI,CX
|
|
MOV AX,[ENDTXT]
|
|
SUB AX,DX
|
|
ADD AX,CX
|
|
CMP AX,[LAST]
|
|
JAE MEMERR
|
|
XCHG AX,[ENDTXT]
|
|
MOV CX,AX
|
|
SUB CX,SI
|
|
CMP SI,DI
|
|
JA DOMOV
|
|
ADD SI,CX
|
|
ADD DI,CX
|
|
STD
|
|
DOMOV:
|
|
INC CX
|
|
|
|
REP
|
|
MOVB
|
|
CLD
|
|
POP CX
|
|
POP DI
|
|
POP SI
|
|
COPYIN:
|
|
REP
|
|
MOVB
|
|
RET
|
|
|
|
DELETE:
|
|
MOV BX,[PARAM1]
|
|
OR BX,BX
|
|
JNZ DELFIN1
|
|
MOV BX,[CURRENT]
|
|
DELFIN1:
|
|
CALL FINDLIN
|
|
JNZ RET
|
|
MOV [CURRENT],BX
|
|
MOV [POINTER],DI
|
|
PUSH DI
|
|
MOV BX,[PARAM2]
|
|
OR BX,BX
|
|
JNZ DELFIN2
|
|
MOV BX,DX
|
|
DELFIN2:
|
|
INC BX
|
|
CALL FINDLIN
|
|
MOV DX,DI
|
|
POP DI
|
|
SUB DX,DI
|
|
XOR CX,CX
|
|
JP REPLACE
|
|
|
|
|
|
GETTEXT:
|
|
|
|
; Inputs:
|
|
; SI points into command line buffer
|
|
; DI points to result buffer
|
|
; Function:
|
|
; Moves [SI] to [DI] until ctrl-Z (1AH) or
|
|
; RETURN (0DH) is found. Termination char not moved.
|
|
; Outputs:
|
|
; AL = Termination character
|
|
; CX = No of characters moved.
|
|
; SI points one past termination character
|
|
; DI points to next free location
|
|
|
|
XOR CX,CX
|
|
|
|
GETIT:
|
|
LODB
|
|
CMP AL,1AH
|
|
JZ RET
|
|
CMP AL,0DH
|
|
JZ RET
|
|
STOB
|
|
INC CX
|
|
JP GETIT
|
|
|
|
MEMERR:
|
|
MOV DX,MEMFUL
|
|
MOV AH,PRINTBUF
|
|
INT 21H
|
|
JMP COMMAND
|
|
|
|
|
|
INSERT:
|
|
MOV BX,[PARAM1]
|
|
OR BX,BX
|
|
JNZ INS
|
|
MOV BX,[CURRENT]
|
|
INC BX
|
|
INS:
|
|
CALL FINDLIN
|
|
MOV CX,[ENDTXT] ;Get End-of-text marker
|
|
MOV SI,CX
|
|
SUB CX,DI ;Calculate number of bytes to copy
|
|
INC CX
|
|
MOV DI,[LAST]
|
|
DOWN
|
|
REP
|
|
MOVB
|
|
XCHG SI,DI
|
|
UP
|
|
INC DI
|
|
MOV BP,SI
|
|
MOV BX,DX
|
|
INLP:
|
|
CALL SHOWNUM
|
|
MOV DX,EDITBUF
|
|
MOV AH,INBUF
|
|
INT 21H
|
|
MOV AL,10
|
|
CALL OUT
|
|
MOV SI,EDITBUF+2
|
|
CMP B,[SI],1AH
|
|
JZ ENDINS
|
|
MOV CL,[SI-1]
|
|
MOV CH,0
|
|
MOV DX,SI
|
|
ADD DX,CX
|
|
INC DX
|
|
CMP DX,BP ;Will it fit?
|
|
JNC MEMERR
|
|
REP
|
|
MOVB
|
|
MOVB
|
|
MOV AL,10
|
|
STOB
|
|
INC BX
|
|
JP INLP
|
|
ENDINS:
|
|
MOV [POINTER],DI
|
|
MOV [CURRENT],BX
|
|
MOV SI,BP
|
|
INC SI
|
|
MOV CX,[LAST]
|
|
SUB CX,BP
|
|
REP
|
|
MOVB
|
|
DEC DI
|
|
MOV [ENDTXT],DI
|
|
RET
|
|
|
|
ENDED:
|
|
;Write text out to .$$$ file
|
|
MOV DI,[ENDTXT]
|
|
MOV CX,128
|
|
MOV AL,1AH
|
|
REP
|
|
STOB
|
|
MOV CX,[ENDTXT]
|
|
CALL NUMRECS
|
|
INC CX
|
|
MOV [FCB2+RR],0
|
|
MOV DX,FCB2
|
|
MOV AH,WRBLK
|
|
INT 21H
|
|
OR AL,AL
|
|
JNZ WRTERR
|
|
;Close .$$$ file
|
|
MOV AH,CLOSE
|
|
INT 21H
|
|
MOV SI,FCB
|
|
LEA DI,[SI+16]
|
|
MOV DX,SI
|
|
MOV CX,9
|
|
REP
|
|
MOVB
|
|
MOV SI,BAK
|
|
MOVW
|
|
MOVB
|
|
;Rename original file .BAK
|
|
MOV AH,RENAM
|
|
INT 21H
|
|
MOV SI,FCB
|
|
MOV DI,FCB2+16
|
|
MOV CX,6
|
|
REP
|
|
MOVW
|
|
;Rename .$$$ file to original name
|
|
MOV DX,FCB2
|
|
INT 21H
|
|
JMP 0
|
|
|
|
|
|
WRTERR:
|
|
MOV DX,DSKFUL
|
|
ERROR:
|
|
MOV AH,PRINTBUF
|
|
INT 21H
|
|
JMP 0
|
|
|
|
NUMRECS:
|
|
SUB CX,START
|
|
AND CL,80H
|
|
ROL CX
|
|
XCHG CL,CH
|
|
RET
|
|
|
|
OUT:
|
|
PUSH DX
|
|
XCHG AX,DX
|
|
MOV AH,OUTCH
|
|
INT 21H
|
|
XCHG AX,DX
|
|
POP DX
|
|
RET
|
|
|
|
BREAK:
|
|
IRET
|
|
|
|
|
|
BAK: DB "BAK"
|
|
NOBAK: DB "Cannot edit .BAK file--rename file$"
|
|
NODIR: DB "No room in directory for file$"
|
|
TOBIG: DB "File too big to fit into memory$"
|
|
NOEOF: DB "No end-of-file mark found in file$"
|
|
DSKFUL: DB "Disk full--file write not completed$"
|
|
MEMFUL: DB 13,10,"Memory full",13,10,"$"
|
|
BADCOM: DB "Entry error",13,10,"$"
|
|
NEWFIL: DB "New file",13,10,"$"
|
|
FCB2: DS 36
|
|
PARAM1: DS 2
|
|
PARAM2: DS 2
|
|
QFLG: DS 1
|
|
HAVEOF: DS 1
|
|
OLDLEN: DS 1
|
|
CURRENT: DS 2
|
|
POINTER: DS 2
|
|
LAST: DS 2
|
|
ENDTXT: DS 2
|
|
COMBUF: DS 2+128
|
|
EDITBUF: DS 2+255
|
|
DS 40
|
|
ALIGN
|
|
STACK:
|
|
START:
|
|
|