Digital Research
This commit is contained in:
2020-11-06 18:50:37 +01:00
parent 621ed8ccaf
commit 31738079c4
8481 changed files with 1888323 additions and 0 deletions

View File

@@ -0,0 +1,284 @@
; Figure 5-8
;
;--------------------------------------------------------------
; TESTBED CODE
; Because of the complexity of this subroutine, the actual
; testbed code has been left in this example. It assumes
; that DDT or ZSID will be used to checkout
IF 1 ;Change to IF 0 to disable testbed
ORG 100H
JMP START ;Bypass "variables" setup by DDT
OPTIONS: DB 0 ;Option Flags
TERMS: DB 'A','E','I',0 ;Terminators
BUFFER DB 5 ;Max. Characters in Buffer
DB 0 ;Actual Count
DB 99,99,99,99,99,99,99 ;Data Bytes
START:
LXI H,BUFFER ;Get address of buffer
LXI D,TERMS ;Address of terminator table
LDA OPTIONS ;Get options set by DDT
MOV B,A ;Put in correct register
CALL RCS ;Enter subroutine
CALL 38H ;Force DDT breakpoint
JMP START ;Test again
ENDIF ;End of testbed x`ce
;---------------------------------------------------------------
;
; RCS : Read Console String (using Raw Input)
;
; Reads a string of characters into a memory buffer using
; Raw Input. Supports options :
;
; * to echo characters or not (when echoing, a Carriage
; Return will be echoed followed by Line Feed)
; * warm boot on input of Control-C or not
; * terminating input either on :
; - max. no of chars input
; - matching terminator character
;
; Calling Sequence
;
; LXI H,BUFFER Buffer has structure
; BUFFER: DB 10 Max. size
; DB 0 Actual Read
; DS 10+1 Buffer area
; MVI B,OPTIONS Options required (see EQUates)
; LXI D,TERMS Pointer to 00H-byte terminated
; Chars, any one of which is a terminator.
; CALL RCS
;
; Exit Parameters
;
; BUFFER : Updated with data bytes and actual character count
; input. (Does not include the terminator).
; A = Terminating Code
; 0 = Maximum number of characters input.
; NZ = Terminator character found.
;
RCS$ECHO EQU 0000$0001B ;Input characters to be echoed
RCS$ABORT EQU 0000$0010B ;Abort on Control-C
RCS$FOLD EQU 0000$0100B ;Fold lower case to upper
RCS$TERM EQU 0000$1000B ;DE -> Term. char. set
;
B$DIRCONIO EQU 6 ;Direct console I/O
BDOS EQU 5 ;BDOS entry point
CTL$C EQU 03H ;Control-C
CR EQU 0DH ;Carriage Return
LF EQU 0AH ;Line Feed
BS EQU 08H ;Backspace
RCS$ST: ;Internal standard terminator table
DB 0DH ;Carriage return
DB 0AH ;Line feed
DB 0 ;End of table
;
RCS$BSS: ;Destructive backspace sequence
DB BS,' ',BS,0
;
RCS: ;<<<<< Main Entry
INX H ;HL -> Actual count
MVI M,0 ;Reset to initial state
DCX H ;HL -> Max. count
RCS$L:
PUSH H ;Save buffer pointer
CALL RCS$GC ;Get character and execute :
; ECHO, ABORT, and FOLD options
;C = character input
POP H ;Recover buffer pointer
MVI A,RCS$TERM ;Check if user-specified terminator
ANA B ;B = options
JNZ RCS$UST ;User specified terminators
LXI D,RCS$ST ;Standard terminators
RCS$UST:
CALL RCS$CT ;Check for terminator
JZ RCS$NOTT ;Not terminator
MOV B,A ;Preserve terminating char
RCS$MCI: ;(Max. char input shares this code)
MVI C,0 ;Terminate buffer
CALL RCS$SC ;Save character
MOV A,B ;Recover terminating char
ORA A ;Set flags
RET
RCS$NOTT: ;Not a terminator
MVI A,BS ;Check for backspace
CMP C
JZ RCS$BS ;Backspace entered
CALL RCS$SC ;Save character in buffer
CALL RCS$UC ;Update count
JNZ RCS$L ;Not max. so get another char
MVI B,0 ;Fake terminating char
JMP RCS$MCI ;A = 0 for max. chars input
;
RCS$BS: ;Backspace entered
PUSH H ;Save buffer pointer
INX H ;HL -> actual count
DCR M ;Backup one
JM RCS$NBS ;Check if count now -ve
LXI H,RCS$BSS ;HL -> Backspacing sequence
MVI A,RCS$ECHO ;No, check if echoing
ANA B ;(BS will have been echoed if so)
JZ RCS$BSNE ;No, input BS not echoed
INX H ;Bypass initial Backspace
RCS$BSNE:
PUSH B ;Save Options and character
PUSH D ;Save terminator table pointer
CALL WCS ;Write console string
POP D ;Recover terminator table pointer
POP B ;Recover options and character
JMP RCS$BSX ;Exit from Backspace logic
RCS$NBS:
INR M ;Reset count to 0
RCS$BSX:
POP H ;Recover buffer pointer
JMP RCS$L ;Get next character
RCS$SC: ;Save character in C in buffer
;HL -> buffer pointer
PUSH D ;Save terminator table pointer
PUSH H ;Save buffer pointer
INX H ;HL -> actual count in buffer
MOV E,M ;Get actual count
INR E ;Count of 0 points to first data byte
MVI D,0 ;Make word value of actual count
DAD D ;HL -> next free data byte
MOV M,C ;Save data byte away
POP H ;Recover buffer pointer
POP D ;Recover terminator table pointer
RET
;
RCS$UC: ;Update buffer count and check for max.
;Return Z set if = to max, NZ if not
;HL -> buffer on entry
PUSH H ;Save buffer pointer
MOV A,M ;Get max. count
INX H ;HL -> actual count
INR M ;Increase actual count
CMP M ;Compare max. to actual
POP H ;Recover buffer pointer
RET ;Z-flag set
;
RCS$GC: ;Get character and execute
; ECHO, ABORT and FOLD options
PUSH D ;Save terminator table pointer
PUSH H ;Save buffer pointer
PUSH B ;Save option flags
RCS$WT:
MVI C,B$DIRCONIO ;Function code
MVI E,0FFH ;Specify input
CALL BDOS
ORA A ;Check if data waiting
JZ RCS$WT ;Go back and wait
POP B ;Recover option flags
MOV C,A ;Save data byte
MVI A,RCS$ABORT ;Check if abort option enabled
ANA B
JZ RCS$NA ;No abort
MVI A,CTL$C ;Check for control-C
CMP C
JZ 0 ;Warm boot
RCS$NA:
MVI A,RCS$FOLD ;Check if folding enabled
ANA B
CNZ TOUPPER ;Fold to UPPER CASE
MVI A,RCS$ECHO ;Check if echo required
ANA B
JZ RCS$NE ;No echo required
PUSH B ;Save options and character
MOV E,C ;Move character for output
MVI C,B$DIRCONIO ;Function code
CALL BDOS ;Echo character
POP B ;Recover options and character
MVI A,CR ;Check if Carriage Return
CMP C
JNZ RCS$NE ;No
PUSH B ;Save options and character
MVI C,B$DIRCONIO ;Function code
MVI E,LF ;Output line feed
CALL BDOS
POP B ;Recover options and character
RCS$NE:
POP H ;Recover buffer pointer
POP D ;Recover terminator table
RET ;Character in C
;
RCS$CT: ;Check for terminator
;C = character just input
;DE -> 00-byte character string of Term. Chars
;Returns Z status if no match found, NZ if found
; (with A = C = Terminating character)
PUSH D ;Save table pointer
RCS$CTL:
LDAX D ;Get next terminator character
ORA A ;Check for end of table
JZ RCS$CTX ;No terminator matched
CMP C ;Compare to input character
JZ RCS$CTX ;Terminator matched
INX D ;Move to next terminator
JMP RCS$CTL ;loop to try next character in table
RCS$CTX: ;Check terminator exit
ORA A ;At this point, A will either be 0
; if the end of the table has been
; reached, or NZ if a match has been
; found. The Z-flag will be set.
POP D ;Recover table pointer
RET
;
; TOUPPER - Fold lower case letters to upper
;
; C = Character on entry and exit
;
TOUPPER:
MVI A,'a'-1 ;Check if folding needed
CMP C ;Compare to input char
JNC TOUPX ;No, char is < or = 'a'-1
MVI A,'z' ;Maybe, char is = or > 'a'
CMP C
JC TOUPX ;No, char is > 'z'
MVI A,0DFH ;Fold character
ANA C
MOV C,A ;Return folded character
TOUPX:
RET
;
;
; WCS - Write Console String (Using Raw I/O)
;
; Output terminates when a 00H byte is encountered.
; A Carriage Return is output when a Line Feed is
; encountered.
;
; Calling sequence
;
; LXI H,BUFFER
; CALL WCS
;
; Exit Parameters
;
; HL -> 00H byte terminator
;
;
WCS:
PUSH H ;Save buffer pointer
MOV A,M ;Get next character
ORA A ;Check if 00H
JZ WCSX ;Yes, exit
CPI LF ;Check if Line Feed
CZ WCSLF ;Yes, O/P CR
MOV E,A ;Character to be output
MVI C,B$DIRCONIO ;Function Code
CALL BDOS ;Output character
POP H ;Recover Buffer pointer
INX H ;Update to next char.
JMP WCS ;Output next char
WCSLF: ;Line Feed encountered
MVI C,B$DIRCONIO ;Function Code
MVI E,CR ;Output a CR
CALL BDOS
MVI A,LF ;Recreate Line Feed
RET ;Output LF
WCSX: ;Exit
POP H ;Balance the stack
RET