Files
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

284 lines
8.0 KiB
NASM
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

; 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