; 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