;*********************************************************************** ; ; PROGRAM: 8080A BOARD MONITOR ; ; COPYRIGHT (C) 1975 ; INTEL CORPORATION ; 3065 BOWERS AVENUE ; SANTA CLARA, CALIFORNIA 95051 ; ;*********************************************************************** ; ; ABSTRACT ; ======== ; ; THIS PROGRAM RUNS ON THE 8080A BOARD AND IS DESIGNED TO PROVIDE ; THE USER WITH A MINIMAL MONITOR. BY USING THIS PROGRAM, ; THE USER CAN EXAMINE AND CHANGE MEMORY OR CPU REGISTERS, LOAD ; A PROGRAM (IN ABSOLUTE HEX) INTO RAM, AND EXECUTE INSTRUCTIONS ; ALREADY IN MEMORY. THE MONITOR ALSO PROVIDES THE USER WITH ; ROUTINES FOR PERFORMING CONSOLE I/O. ; ; ; PROGRAM ORGANIZATION ; ======= ============ ; ; THE LISTING IS ORGANIZED IN THE FOLLOWING WAY. FIRST THE COMMAND ; RECOGNIZER, WHICH IS THE HIGHEST LEVEL ROUTINE IN THE PROGRAM. ; NEXT, ARE THE ROUTINES TO IMPLEMENT THE VARIOUS COMMANDS, FINALLY ; THE UTILITY ROUTINES WHICH ACTUALLY DO THE DIRTY WORK. WITHIN ; EACH SECTION, THE ROUTINES ARE ORGANIZED IN ALPHABETICAL ; ORDER, BY ENTRY POINT OF THE ROUTINE. ; ; THIS PROGRAM EXPECTS TO RUN IN THE FIRST 1K OF ADDRESS SPACE. ; IF, FOR SOME REASON, THE PROGRAM IS RE-ORG'ED, CARE SHOULD ; BE TAKEN TO MAKE SURE THAT THE TRANSFER INSTRUCTIONS FOR RST 1 ; AND RST 7 ARE ADJUSTED APPROPRIATELY. ; ; THE PROGRAM ALSO EXPECTS THAT RAM LOCATIONS 5K-1 TO 5K-256, ; INCLUSIVE, ARE RESERVED FOR THE PROGRAM'S OWN USE. THESE ; LOCATIONS MAY BE ALTERED, HOWEVER, BY CHANGING THE EQU'ED ; SYMBOL "DATA" AS DESIRED. ; ; ; LIST OF FUNCTIONS ; ==== == ========= ; ; GETCM ; ----- ; ; DCMD ; GCMD ; ICMD ; MCMD ; SCMD ; XCMD ; ---- ; ; BREAK ; CI ; CNVBN ; CO ; CROUT ; ECHO ; ERROR ; FRET ; GETCH ; GETHX ; GETNM ; HILO ; NMOUT ; PRVAL ; REGDS ; RGADR ; RSTTF ; SRET ; STHF0 ; STHLF ; VALDG ; VALDL ; ----- ; ORG 0H ; ;*********************************************************************** ; ; MONITOR EQUATES ; ;*********************************************************************** ; ; BRCHR EQU 1BH ; CODE FOR BREAK CHARACTER (ESCAPE) BRLOC EQU 13FDH ; LOCATION OF USER BRANCH INSTRUCTION IN RAM BRTAB EQU 3FAH ; LOCATION FOR START OF BRANCH TABLE IN ROM CMD EQU 027H ; COMMAND INSTRUCTION FOR USART INITIALIZATION CNCTL EQU 0FBH ; CONSOLE (USART) CONTROL PORT CNIN EQU 0FAH ; CONSOLE INPUT PORT CNOUT EQU 0FAH ; CONSOLE OUTPUT PORT CONST EQU 0FBH ; CONSOLE STATUS INPUT PORT CR EQU 0DH ; CODE FOR CARRIAGE RETURN DATA EQU 5*1024-256 ; END OF MONITOR RAM USAGE ESC EQU 1BH ; CODE FOR ESCAPE CHARACTER HCHAR EQU 0FH ; MASK TO SELECT LOWER HEX CHAR FROM BYTE INVRT EQU 0FFH ; MASK TO INVERT HALF BYTE FLAG LF EQU 0AH ; CODE FOR LINE FEED LOWER EQU 0 ; DENOTES LOWER HALF OF BYTE IN ICMD ;LSGNON EQU --- ; LENGTH OF SIGNON MESSAGE - DEFINED LATER MODE EQU 0CFH ; MODE SET FOR USART INITIALIZATION ;MSTAK EQU --- ; START OF MONITOR STACK - DEFINED LATER ;NCMDS EQU --- ; NUMBER OF VALID COMMANDS NEWLN EQU 0FH ; MASK FOR CHECKING MEMORY ADDR DISPLAY PRTY0 EQU 07FH ; MASK TO CLEAR PARITY BIT FROM CONSOLE CHAR REGS EQU DATA+255-18 ; START OF REGISTER SAVE AREA RBR EQU 2 ; MASK TO TEST RECEIVER STATUS RSTU EQU 38H ; TRANSFER LOCATION FOR RST7 INSTRUCTION ;RTABS EQU --- ; SIZE OF ENTRY IN RTAB TABLE TERM EQU 1BH ; CODE FOR ICMD TERMINATING CHARACTER (ESCAPE) TRDY EQU 1 ; MASK TO TEST TRANSMITTER STATUS UPPER EQU 0FFH ; DENOTES UPPER HALF OF BYTE IN ICMD ; ;***************************************************************** ; ; MONITOR MACROS ; ;***************************************************************** ; ; ;TRUE MACRO WHERE ; BRANCH IF FUNCTION RETURNS TRUE (SUCCESS) ; JC WHERE ; ENDM ; ;FALSE MACRO WHERE ; BRANCH IF FUNCTION RETURNS FALSE (FAILURE) ; JNC WHERE ; ENDM ; ; ;***************************************************************** ; ; USART INITIALIZATION CODE ; ;***************************************************************** ; ; ; THE USART IS ASSUMED TO COME UP IN THE RESET POSITION (THIS ; FUNCTION IS TAKEN CARE OF BY THE HARDWARE). THE USART WILL ; BE INITIALIZED IN THE SAME WAY FOR EITHER A TTY OR CRT ; INTERFACE. THE FOLLOWING PARAMETERS ARE USED: ; ; MODE INSTRUCTION ; ==== =========== ; ; 2 STOP BITS ; PARITY DISABLED ; 8 BIT CHARACTERS ; BAUD RATE FACTOR OF 64 ; ; COMMAND INSTRUCTION ; ======= =========== ; ; NO HUNT MODE ; NOT(RTS) FORCED TO 0 ; RECEIVE ENABLED ; TRANSMIT ENABLED ; MVI A,MODE OUT CNCTL ; OUTPUT MODE SET TO USART MVI A,CMD ; OUT CNCTL ; OUTPUT COMMAND WORD TO USART ; ;***************************************************************** ; ; RESTART ENTRY POINT ; ;***************************************************************** ; ; GO: SHLD LSAVE ; SAVE HL REGISTERS POP H ; GET TOP OF STACK ENTRY SHLD PSAVE ; ASSUME THIS IS LAST P COUNTER LXI H,0 ; CLEAR HL DAD SP ; GET STACK POINTER VALUE SHLD SSAVE ; SAVE USER`S STACK POINTER LXI H,ASAVE+1 ; NEW VALUE FOR STACK POINTER SPHL ; SET MONITOR STACK POINTER FOR REG SAVE PUSH PSW ; SAVE A AND FLAGS PUSH B ; SAVE B AND C PUSH D ; SAVE D AND E ; ;************************************************************ ; ; PRINT SIGNON MESSAGE ; ;************************************************************ ; ; SOMSG: LXI H,SGNON ; GET ADDRESS OF SIGNON MESSAGE MVI B,LSGNON ; COUNTER FOR CHARACTERS IN MESSAGE MSGL: MOV C,M ; FETCH NEXT CHAR TO C REG CALL CO ; SEND IT TO THE CONSOLE INX H ; POINT TO NEXT CHARACTER DCR B ; DECREMENT BYTE COUNTER JNZ MSGL ; RETURN FOR NEXT CHARACTER ; ; ;***************************************************************** ; ; COMMAND RECOGNIZING ROUTINE ; ;***************************************************************** ; ; FUNCTION: GETCM ; INPUTS: NONE ; OUTPUTS: NONE ; CALLS: GETCH,ECHO,ERROR ; DESTROYS: A,B,C,H,L,F/F'S ; DESCRIPTION: GETCM RECEIVES AN INPUT CHARACTER FROM THE USER ; AND ATTEMPTS TO LOCATE THIS CHARACTER IN ITS COMMAND ; CHARACTER TABLE. IF SUCCESSFUL, THE ROUTINE ; CORRESPONDING TO THIS CHARACTER IS SELECTED FROM ; A TABLE OF COMMAND ROUTINE ADDRESSES, AND CONTROL ; IS TRANSFERRED TO THIS ROUTINE. IF THE CHARACTER ; DOES NOT MATCH ANY ENTRIES, CONTROL IS PASSED TO ; THE ERROR HANDLER. ; GETCM: LXI H,MSTAK ; ALWAYS WANT TO RESET STACK PTR TO MONITOR SPHL ; /STARTING VALUE SO ROUTINES NEEDN'T CLEAN UP MVI C,'.' ; PROMPT CHARACTER TO C CALL ECHO ; SEND PROMPT CHARACTER TO USER TERMINAL JMP GTC03 ; WANT TO LEAVE ROOM FOR RST BRANCH ; ORG RSTU ; ORG TO RST TRANSFER LOCATION JMP USRBR ; JUMP TO USER BRANCH LOCATION ; GTC03: CALL GETCH ; GET COMMAND CHARACTER TO A CALL ECHO ; ECHO CHARACTER TO USER MOV A,C ; PUT COMMAND CHARACTER INTO ACCUMULATOR LXI B,NCMDS ; C CONTAINS LOOP AND INDEX COUNT LXI H,CTAB ; HL POINTS INTO COMMAND TABLE GTC05: CMP M ; COMPARE TABLE ENTRY AND CHARACTER JZ GTC10 ; BRANCH IF EQUAL - COMMAND RECOGNIZED INX H ; ELSE, INCREMENT TABLE POINTER DCR C ; DECREMENT LOOP COUNT JNZ GTC05 ; BRANCH IF NOT AT TABLE END JMP ERROR ; ELSE, COMMAND CHARACTER IS ILLEGAL GTC10: LXI H,CADR ; IF GOOD COMMAND, LOAD ADDRESS OF TABLE ; /OF COMMAND ROUTINE ADDRESSES DAD B ; ADD WHAT IS LEFT OF LOOP COUNT DAD B ; ADD AGAIN - EACH ENTRY IN CADR IS 2 BYTES LONG MOV A,M ; GET LSP OF ADDRESS OF TABLE ENTRY TO A INX H ; POINT TO NEXT BYTE IN TABLE MOV H,M ; GET MSP OF ADDRESS OF TABLE ENTRY TO H MOV L,A ; PUT LSP OF ADDRESS OF TABLE ENTRY INTO L PCHL ; NEXT INSTRUCTION COMES FROM COMMAND ROUTINE ; ; ;********************************************************************** ; ; COMMAND IMPLEMENTING ROUTINES ; ;********************************************************************** ; ; ; FUNCTION: DCMD ; INPUTS: NONE ; OUTPUTS: NONE ; CALLS: ECHO,NMOUT,HILO,GETCM,CROUT,GETNM ; DESTROYS: A,B,C,D,E,H,L,F/F'S ; DESCRIPTION: DCMD IMPLEMENTS THE DISPLAY MEMORY (D) COMMAND ; DCMD: MVI C,2 ; GET TWO NUMBERS FROM INPUT STREAM CALL GETNM POP D ; ENDING ADDRESS TO DE POP H ; STARTING ADDRESS TO HL DCM05: CALL CROUT ; ECHO CARRIAGE RETURN/LINE FEED MOV A,H ; DISPLAY ADDRESS OF FIRST LOCATION IN LINE CALL NMOUT ; MOV A,L ; ADDRESS IS 2 BYTES LONG CALL NMOUT ; DCM10: MVI C,' ' CALL ECHO ; USE BLANK AS SEPARATOR MOV A,M ; GET CONTENTS OF NEXT MEMORY LOCATION CALL NMOUT ; DISPLAY CONTENTS CALL BREAK ; SEE IF USER WANTS OUT ; TRUE DCM12 ; IF SO, BRANCH JC DCM12 ; IF SO, BRANCH CALL HILO ; SEE IF ADDRESS OF DISPLAYED LOCATION IS ; /GREATER THAN OR EQUAL TO ENDING ADDRESS ; FALSE DCM15 ; IF NOT, MORE TO DISPLAY JNC DCM15 ; IF NOT, MORE TO DISPLAY DCM12: CALL CROUT ; CARRIAGE RETURN/LINE FEED TO END LINE JMP GETCM ; ALL DONE DCM15: INX H ; IF MORE TO GO, POINT TO NEXT LOC TO DISPLAY MOV A,L ; GET LOW ORDER BITS OF NEW ADDRESS ANI NEWLN ; SEE IF LAST HEX DIGIT OF ADDRESS DENOTES ; /START OF NEW LINE JNZ DCM10 ; NO - NOT AT END OF LINE JMP DCM05 ; YES - START NEW LINE WITH ADDRESS ; ; ;***************************************************************** ; ; ; FUNCTION: GCMD ; INPUTS: NONE ; OUTPUTS: NONE ; CALLS: ERROR,GETHX,RSTTF ; DESTROYS: A,B,C,D,E,H,L,F/F'S ; DESCRIPTION: GCMD IMPLEMENTS THE BEGIN EXECUTION (G) COMMAND. ; GCMD: CALL GETHX ; GET ADDRESS (IF PRESENT) FROM INPUT STREAM ; FALSE GCM05 ; BRANCH IF NO NUMBER PRESENT JNC GCM05 ; BRANCH IF NO NUMBER PRESENT MOV A,D ; ELSE, GET TERMINATOR CPI CR ; SEE IF CARRIAGE RETURN JNZ ERROR ; ERROR IF NOT PROPERLY TERMINATED LXI H,PSAVE ; WANT NUMBER TO REPLACE SAVE PGM COUNTER MOV M,C INX H MOV M,B JMP GCM10 GCM05: MOV A,D ; IF NO STARTING ADDRESS, MAKE SURE THAT CPI CR ; /CARRIAGE RETURN TERMINATED COMMAND JNZ ERROR ; ERROR IF NOT GCM10: JMP RSTTF ; RESTORE REGISTERS AND BEGIN EXECUTION ; ; ;***************************************************************** ; ; ; FUNCTION: ICMD ; INPUTS: NONE ; OUTPUTS: NONE ; CALLS: ERROR,ECHO,GETCH,VALDL,VALDG,CNVBN,STHLF,GETNM,CROUT ; DESTROYS: A,B,C,D,E,H,L,F/F'S ; DESCRIPTION: ICMD IMPLEMENTS THE INSERT CODE INTO MEMORY (I) COMMAND. ; ICMD: MVI C,1 CALL GETNM ; GET SINGLE NUMBER FROM INPUT STREAM MVI A,UPPER STA TEMP ; TEMP WILL HOLD THE UPPER/LOWER HALF BYTE FLAG POP D ; ADDRESS OF START TO DE ICM05: CALL GETCH ; GET A CHARACTER FROM INPUT STREAM MOV C,A ; CALL ECHO ; ECHO IT MOV A,C ; PUT CHARACTER BACK INTO A CPI TERM ; SEE IF CHARACTER IS A TERMINATING CHARACTER JZ ICM25 ; IF SO, ALL DONE ENTERING CHARACTERS CALL VALDL ; ELSE, SEE IF VALID DELIMITER ; TRUE ICM05 ; IF SO SIMPLY IGNORE THIS CHARACTER JC ICM05 ; IF SO SIMPLY IGNORE THIS CHARACTER CALL VALDG ; ELSE, CHECK TO SEE IF VALID HEX DIGIT ; FALSE ICM20 ; IF NOT, BRANCH TO HANDLE ERROR CONDITION JNC ICM20 ; IF NOT, BRANCH TO HANDLE ERROR CONDITION CALL CNVBN ; CONVERT DIGIT TO BINARY MOV C,A ; MOVE RESULT TO C CALL STHLF ; STORE IN APPROPRIATE HALF WORD LDA TEMP ; GET HALF BYTE FLAG ORA A ; SET F/F'S JNZ ICM10 ; BRANCH IF FLAG SET FOR UPPER INX D ; IF LOWER, INC ADDRESS OF BYTE TO STORE IN ICM10: XRI INVRT ; TOGGLE STATE OF FLAG STA TEMP ; PUT NEW VALUE OF FLAG BACK JMP ICM05 ; PROCESS NEXT DIGIT ICM20: CALL STHF0 ; ILLEGAL CHARACTER JMP ERROR ; MAKE SURE ENTIRE BYTE FILLED THEN ERROR ICM25: CALL STHF0 ; HERE FOR ESCAPE CHARACTER - INPUT IS DONE CALL CROUT ; ADD CARRIAGE RETURN JMP GETCM ; ; ; ;***************************************************************** ; ; ; FUNCTION: MCMD ; INPUTS: NONE ; OUTPUTS: NONE ; CALLS: GETCM,HILO,GETNM ; DESTROYS: A,B,C,D,E,H,L,F/F'S ; DESCRIPTION: MCMD IMPLEMENTS THE MOVE DATA IN MEMORY (M) COMMAND. ; MCMD: MVI C,3 ; CALL GETNM ; GET 3 NUMBERS FROM INPUT STREAM POP B ; DESTINATION ADDRESS TO BC POP H ; ENDING ADDRESS TO HL POP D ; STARTING ADDRESS TO DE MCM05: PUSH H ; SAVE ENDING ADDRESS MOV H,D MOV L,E ; SOURCE ADDRESS TO HL MOV A,M ; GET SOURCE BYTE MOV H,B MOV L,C ; DESTINATION ADDRESS TO HL MOV M,A ; MOVE BYTE TO DESTINATION INX B ; INCREMENT DESTINATION ADDRESS MOV A,B ORA C ; TEST FOR DESTINATION ADDRESS OVERFLOW JZ GETCM ; IF SO, CAN TERMINATE COMMAND INX D ; INCREMENT SOURCE ADDRESS POP H ; ELSE, GET BACK ENDING ADDRESS CALL HILO ; SEE IF ENDING ADDR>=SOURCE ADDR ; FALSE GETCM ; IF NOT, COMMAND IS DONE JNC GETCM ; IF NOT, COMMAND IS DONE JMP MCM05 ; MOVE ANOTHER BYTE ; ; ;**************************************************************** ; ; ; FUNCTION: SCMD ; INPUTS: NONE ; OUTPUTS: NONE ; CALLS: GETHX,GETCM,NMOUT,ECHO ; DESTROYS: A,B,C,D,E,H,L,F/F'S ; DESCRIPTION: SCMD IMPLEMENTS THE SUBSTITUTE INTO MEMORY (S) COMMAND. ; SCMD: CALL GETHX ; GET A NUMBER, IF PRESENT, FROM INPUT PUSH B POP H ; GET NUMBER TO HL - DENOTES MEMORY LOCATION SCM05: MOV A,D ; GET TERMINATOR CPI ' ' ; SEE IF SPACE JZ SCM10 ; YES - CONTINUE PROCESSING CPI ',' ; ELSE, SEE IF COMMA JNZ GETCM ; NO - TERMINATE COMMAND SCM10: MOV A,M ; GET CONTENTS OF SPECIFIED LOCATION TO A CALL NMOUT ; DISPLAY CONTENTS ON CONSOLE MVI C,'-' CALL ECHO ; USE DASH FOR SEPARATOR CALL GETHX ; GET NEW VALUE FOR MEMORY LOCATION, IF ANY ; FALSE SCM15 ; IF NO VALUE PRESENT, BRANCH JNC SCM15 ; IF NO VALUE PRESENT, BRANCH MOV M,C ; ELSE, STORE LOWER 8 BITS OF NUMBER ENTERED SCM15: INX H ; INCREMENT ADDRESS OF MEMORY LOCATION TO VIEW JMP SCM05 ; ; ;***************************************************************** ; ; ; FUNCTION: XCMD ; INPUTS: NONE ; OUTPUTS: NONE ; CALLS: GETCH,ECHO,REGDS,GETCM,ERROR,RGADR,NMOUT,CROUT,GETHX ; DESTROYS: A,B,C,D,E,H,L,F/F'S ; DESCRIPTION: XCMD IMPLEMENTS THE REGISTER EXAMINE AND CHANGE (X) ; COMMAND. ; XCMD: CALL GETCH ; GET REGISTER IDENTIFIER MOV C,A ; CALL ECHO ; ECHO IT MOV A,C CPI CR JNZ XCM05 ; BRANCH IF NOT CARRIAGE RETURN CALL REGDS ; ELSE, DISPLAY REGISTER CONTENTS JMP GETCM ; THEN TERMINATE COMMAND XCM05: MOV C,A ; GET REGISTER IDENTIFIER TO C CALL RGADR ; CONVERT IDENTIFIER INTO RTAB TABLE ADDR PUSH B POP H ; PUT POINTER TO REGISTER ENTRY INTO HL MVI C,' ' CALL ECHO ; ECHO SPACE TO USER MOV A,C STA TEMP ; PUT SPACE INTO TEMP AS DELIMITER XCM10: LDA TEMP ; GET TERMINATOR CPI ' ' ; SEE IF A BLANK JZ XCM15 ; YES - GO CHECK POINTER INTO TABLE CPI ',' ; NO - SEE IF COMMA JNZ GETCM ; NO - MUST BE CARRIAGE RETURN TO END COMMAND XCM15: MOV A,M ORA A ; SET F/F'S JNZ XCM18 ; BRANCH IF NOT AT END OF TABLE CALL CROUT ; ELSE, OUTPUT CARRIAGE RETURN LINE FEED JMP GETCM ; AND EXIT XCM18: PUSH H ; PUT POINTER ON STACK MOV E,M MVI D,DATA SHR 8 ; FETCH ADDRESS OF SAVE LOCATION FROM TABLE INX H ; MOV B,M ; FETCH LENGTH FLAG FROM TABLE PUSH D ; SAVE ADDRESS OF SAVE LOCATION PUSH D POP H ; MOVE ADDRESS TO HL PUSH B ; SAVE LENGTH FLAG MOV A,M ; GET 8 BITS OF REGISTER FROM SAVE LOCATION CALL NMOUT ; DISPLAY IT POP PSW ; GET BACK LENGTH FLAG PUSH PSW ; SAVE IT AGAIN ORA A ; SET F/F'S JZ XCM20 ; IF 8 BIT REGISTER, NOTHING MORE TO DISPLAY DCX H ; ELSE, FOR 16 BIT REGISTER, GET LOWER 8 BITS MOV A,M CALL NMOUT ; DISPLAY THEM XCM20: MVI C,'-' CALL ECHO ; USE DASH AS SEPARATOR CALL GETHX ; SEE IF THERE IS A VALUE TO PUT INTO REGISTER ; FALSE XCM30 ; NO - GO CHECK FOR NEXT REGISTER JNC XCM30 ; NO - GO CHECK FOR NEXT REGISTER MOV A,D ; STA TEMP ; ELSE, SAVE THE TERMINATOR FOR NOW POP PSW ; GET BACK LENGTH FLAG POP H ; PUT ADDRESS OF SAVE LOCATION INTO HL ORA A ; SET F/F'S JZ XCM25 ; IF 8 BIT REGISTER, BRANCH MOV M,B ; SAVE UPPER 8 BITS DCX H ; POINT TO SAVE LOCATION FOR LOWER 8 BITS XCM25: MOV M,C ; STORE ALL OF 8 BIT OR LOWER 1/2 OF 16 BIT REG XCM27: LXI D,RTABS ; SIZE OF ENTRY IN RTAB TABLE POP H ; POINTER INTO REGISTER TABLE RTAB DAD D ; ADD ENTRY SIZE TO POINTER JMP XCM10 ; DO NEXT REGISTER XCM30: MOV A,D ; GET TERMINATOR STA TEMP ; SAVE IN MEMORY POP D ; CLEAR STACK OF LENGTH FLAG AND ADDRESS POP D ; /OF SAVE LOCATION JMP XCM27 ; GO INCREMENT REGISTER TABLE POINTER ; ; ;***************************************************************** ; ; UTILITY ROUTINES ; ;***************************************************************** ; ; ; FUNCTION: BREAK ; INPUTS: NONE ; OUTPUTS: CARRY - 1 IF ESCAPE CHARACTER INPUT ; - 0 IF ANY OTHER CHARACTER OR NO CHARACTER PENDING ; CALLS: NOTHING ; DESTROYS: A,F/F'S ; DESCRIPTION: BREAK IS USED TO SENSE AN ESCAPE CHARACTER FROM ; THE USER. IF NO CHARACTER IS PENDING, OR IF THE ; PENDING CHARACTER IS NOT THE ESCAPE, THEN A FAILURE ; RETURN (CARRY=0) IS TAKEN. IN THIS CASE, THE ; PENDING CHARACTER (IF ANY) IS LOST. IF THE PENDING ; CHARACTER IS AN ESCAPE CHARACTER, BREAK TAKES A SUCCESS ; RETURN (CARRY=1). ; BREAK: IN CONST ; GET CONSOLE STATUS ANI RBR ; SEE IF CHARACTER PENDING JZ FRET ; NO - TAKE FAILURE RETURN IN CNIN ; YES - PICK UP CHARACTER ANI PRTY0 ; STRIP OFF PARITY BIT CPI BRCHR ; SEE IF BREAK CHARACTER JZ SRET ; YES - SUCCESS RETURN JMP FRET ; NO - FAILURE RETURN - CHARACTER LOST ; ; ;***************************************************************** ; ; ; FUNCTION: CI ; INPUTS: NONE ; OUTPUTS: A - CHARACTER FROM CONSOLE ; CALLS: NOTHING ; DESTROYS: A,F/F'S ; DESCRIPTION: CI WAITS UNTIL A CHARACTER HAS BEEN ENTERED AT THE ; CONSOLE AND THEN RETURNS THE CHARACTER, VIA THE A ; REGISTER, TO THE CALLING ROUTINE. THIS ROUTINE ; IS CALLED BY THE USER VIA A JUMP TABLE IN RAM. ; CI: IN CONST ; GET STATUS OF CONSOLE ANI RBR ; CHECK FOR RECEIVER BUFFER READY JZ CI ; NOT YET - WAIT IN CNIN ; READY SO GET CHARACTER RET ; ; ;****************************************************************** ; ; ; FUNCTION: CNVBN ; INPUTS: C - ASCII CHARACTER '0'-'9' OR 'A'-'F' ; OUTPUTS: A - 0 TO F HEX ; CALLS: NOTHING ; DESTROYS: A,F/F'S ; DESCRIPTION: CNVBN CONVERTS THE ASCII REPRESENTATION OF A HEX ; CHARACTER INTO ITS CORRESPONDING BINARY VALUE. CNVBN ; DOES NOT CHECK THE VALIDITY OF ITS INPUT. ; CNVBN: MOV A,C SUI '0' ; SUBTRACT CODE FOR '0' FROM ARGUMENT CPI 10 ; WANT TO TEST FOR RESULT OF 0 TO 9 RM ; IF SO, THEN ALL DONE SUI 7 ; ELSE, RESULT BETWEEN 17 AND 23 DECIMAL RET ; SO RETURN AFTER SUBTRACTING BIAS OF 7 ; ; ;********************************************************************** ; ; ; FUNCTION: CO ; INPUTS: C - CHARACTER TO OUTPUT TO CONSOLE ; OUTPUTS: C - CHARACTER OUTPUT TO CONSOLE ; CALLS: NOTHING ; DESTROYS: A,F/F'S ; DESCRIPTION: CO WAITS UNTIL THE CONSOLE IS READY TO ACCEPT A CHARACTER ; AND THEN SENDS THE INPUT ARGUMENT TO THE CONSOLE. ; CO: IN CONST ; GET STATUS OF CONSOLE ANI TRDY ; SEE IF TRANSMITTER READY JZ CO ; NO - WAIT MOV A,C ; ELSE, MOVE CHARACTER TO A REGISTER FOR OUTPUT OUT CNOUT ; SEND TO CONSOLE RET ; ; ;***************************************************************** ; ; ; FUNCTION CROUT ; INPUTS: NONE ; OUTPUTS: NONE ; CALLS: ECHO ; DESTROYS: A,B,C,F/F'S ; DESCRIPTION: CROUT SENDS A CARRIAGE RETURN (AND HENCE A LINE ; FEED) TO THE CONSOLE. ; CROUT: MVI C,CR CALL ECHO ; OUTPUT CARRIAGE RETURN TO USER TERMINAL RET ; ; ;***************************************************************** ; ; ; FUNCTION: ECHO ; INPUTS: C - CHARACTER TO ECHO TO TERMINAL ; OUTPUTS: C - CHARACTER ECHOED TO TERMINAL ; CALLS: CO ; DESTROYS: A,B,F/F'S ; DESCRIPTION: ECHO TAKES A SINGLE CHARACTER AS INPUT AND, VIA ; THE MONITOR, SENDS THAT CHARACTER TO THE USER ; TERMINAL. A CARRIAGE RETURN IS ECHOED AS A CARRIAGE ; RETURN LINE FEED, AND AN ESCAPE CHARACTER IS ECHOED AS $. ; ECHO: MOV B,C ; SAVE ARGUMENT MVI A,ESC CMP B ; SEE IF ECHOING AN ESCAPE CHARACTER JNZ ECH05 ; NO - BRANCH MVI C,'$' ; YES - ECHO AS $ ECH05: CALL CO ; DO OUTPUT THROUGH MONITOR MVI A,CR CMP B ; SEE IF CHARACTER ECHOED WAS A CARRIAGE RETURN JNZ ECH10 ; NO - NO NEED TO TAKE SPECIAL ACTION MVI C,LF ; YES - WANT TO ECHO LINE FEED, TOO CALL CO ECH10: MOV C,B ; RESTORE ARGUMENT RET ; ; ;********************************************************************** ; ; ; FUNCTION: ERROR ; INPUTS: NONE ; OUTPUTS: NONE ; CALLS: ECHO,CROUT,GETCM ; DESTROYS: A,B,C,F/F'S ; DESCRIPTION: ERROR PRINTS THE ERROR CHARACTER (CURRENTLY A NUMBER SIGN) ; ON THE CONSOLE, FOLLOWED BY A CARRIAGE RETURN-LINE FEED, ; AND THEN RETURNS CONTROL TO THE COMMAND RECOGNIZER. ; ERROR: MVI C,'*' CALL ECHO ; SEND # TO CONSOLE EXIT: CALL CROUT ; SKIP TO BEGINNING OF NEXT LINE JMP GETCM ; TRY AGAIN FOR ANOTHER COMMAND ; ; ;********************************************************************** ; ; ; FUNCTION: FRET ; INPUTS: NONE ; OUTPUTS: CARRY - ALWAYS 0 ; CALLS: NOTHING ; DESTROYS: CARRY ; DESCRIPTION: FRET IS JUMPED TO BY ANY ROUTINE THAT WISHES TO ; INDICATE FAILURE ON RETURN. FRET SETS THE CARRY ; FALSE, DENOTING FAILURE, AND THEN RETURNS TO THE ; CALLER OF THE ROUTINE INVOKING FRET. ; FRET: STC ; FIRST SET CARRY TRUE CMC ; THEN COMPLEMENT IT TO MAKE IT FALSE RET ; RETURN APPROPRIATELY ; ; ;********************************************************************** ; ; ; FUNCTION: GETCH ; INPUTS: NONE ; OUTPUTS: C - NEXT CHARACTER IN INPUT STREAM ; CALLS: CI ; DESTROYS: A,C,F/F'S ; DESCRIPTION: GETCH RETURNS THE NEXT CHARACTER IN THE INPUT STREAM ; TO THE CALLING PROGRAM. ; GETCH: CALL CI ; GET CHARACTER FROM TERMINAL ANI PRTY0 ; TURN OFF PARITY BIT IN CASE SET BY CONSOLE MOV C,A ; PUT VALUE IN C REGISTER FOR RETURN RET ; ; ;********************************************************************** ; ; ; FUNCTION: GETHX ; INPUTS: NONE ; OUTPUTS: BC - 16 BIT INTEGER ; D - CHARACTER WHICH TERMINATED THE INTEGER ; CARRY - 1 IF FIRST CHARACTER NOT DELIMITER ; - 0 IF FIRST CHARACTER IS DELIMITER ; CALLS: GETCH,ECHO,VALDL,VALDG,CNVBN,ERROR ; DESTROYS: A,B,C,D,E,F/F'S ; DESCRIPTION: GETHX ACCEPTS A STRING OF HEX DIGITS FROM THE INPUT ; STREAM AND RETURNS THEIR VALUE AS A 16 BIT BINARY ; INTEGER. IF MORE THAN 4 HEX DIGITS ARE ENTERED, ; ONLY THE LAST 4 ARE USED. THE NUMBER TERMINATES WHEN ; A VALID DELIMITER IS ENCOUNTERED. THE DELIMITER IS ; ALSO RETURNED AS AN OUTPUT OF THE FUNCTION. ILLEGAL ; CHARACTERS (NOT HEX DIGITS OR DELIMITERS) CAUSE AN ; ERROR INDICATION. IF THE FIRST (VALID) CHARACTER ; ENCOUNTERED IN THE INPUT STREAM IS NOT A DELIMITER, ; GETHX WILL RETURN WITH THE CARRY BIT SET TO 1; ; OTHERWISE, THE CARRY BIT IS SET TO 0 AND THE CONTENTS ; OF BC ARE UNDEFINED. ; GETHX: PUSH H ; SAVE HL LXI H,0 ; INITIALIZE RESULT MVI E,0 ; INITIALIZE DIGIT FLAG TO FALSE GHX05: CALL GETCH ; GET A CHARACTER MOV C,A ; CALL ECHO ; ECHO THE CHARACTER CALL VALDL ; SEE IF DELIMITER ; FALSE GHX10 ; NO - BRANCH JNC GHX10 ; NO - BRANCH MOV D,C ; YES - ALL DONE, BUT WANT TO RETURN DELIMITER PUSH H POP B ; MOVE RESULT TO BC POP H ; RESTORE HL MOV A,E ; GET FLAG ORA A ; SET F/F'S JNZ SRET ; IF FLAG NON-0, A NUMBER HAS BEEN FOUND JZ FRET ; ELSE, DELIMITER WAS FIRST CHARACTER GHX10: CALL VALDG ; IF NOT DELIMITER, SEE IF DIGIT ; FALSE ERROR ; ERROR IF NOT A VALID DIGIT, EITHER JNC ERROR ; ERROR IF NOT A VALID DIGIT, EITHER CALL CNVBN ; CONVERT DIGIT TO ITS BINARY VALUE MVI E,0FFH ; SET DIGIT FLAG NON-0 DAD H ; *2 DAD H ; *4 DAD H ; *8 DAD H ; *16 MVI B,0 ; CLEAR UPPER 8 BITS OF BC PAIR MOV C,A ; BINARY VALUE OF CHARACTER INTO C DAD B ; ADD THIS VALUE TO PARTIAL RESULT JMP GHX05 ; GET NEXT CHARACTER ; ; ;***************************************************************** ; ; ; FUNCTION: GETNM ; INPUTS: C - COUNT OF NUMBERS TO FIND IN INPUT STREAM ; OUTPUTS: TOP OF STACK - NUMBERS FOUND IN REVERSE ORDER (LAST ON TOP ; OF STACK) ; CALLS: GETHX,HILO,ERROR ; DESTROYS: A,B,C,D,E,H,L,F/F'S ; DESCRIPTION: GETNM FINDS A SPECIFIED COUNT OF NUMBERS, BETWEEN 1 ; AND 3, INCLUSIVE, IN THE INPUT ; STREAM AND RETURNS THEIR VALUES ON THE STACK. IF 2 ; OR MORE NUMBERS ARE REQUESTED, THEN THE FIRST MUST BE ; LESS THAN OR EQUAL TO THE SECOND, OR THE FIRST AND ; SECOND NUMBERS WILL BE SET EQUAL. THE LAST NUMBER ; REQUESTED MUST BE TERMINATED BY A CARRIAGE RETURN ; OR AN ERROR INDICATION WILL RESULT. ; GETNM: MVI L,3 ; PUT MAXIMUM ARGUMENT COUNT INTO L MOV A,C ; GET THE ACTUAL ARGUMENT COUNT ANI 3 ; FORCE TO MAXIMUM OF 3 RZ ; IF 0, DON'T BOTHER TO DO ANYTHIING MOV H,A ; ELSE, PUT ACTUAL COUNT INTO H GNM05: CALL GETHX ; GET A NUMBER FROM INPUT STREAM ; FALSE ERROR ; ERROR IF NOT THERE - TOO FEW NUMBERS JNC ERROR ; ERROR IF NOT THERE - TOO FEW NUMBERS PUSH B ; ELSE, SAVE NUMBER ON STACK DCR L ; DECREMENT MAXIMUM ARGUMENT COUNT DCR H ; DECREMENT ACTUAL ARGUMENT COUNT JZ GNM10 ; BRANCH IF NO MORE NUMBERS WANTED MOV A,D ; ELSE, GET NUMBER TERMINATOR TO A CPI CR ; SEE IF CARRIAGE RETURN JZ ERROR ; ERROR IF SO - TOO FEW NUMBERS JMP GNM05 ; ELSE, PROCESS NEXT NUMBER GNM10: MOV A,D ; WHEN COUNT 0, CHECK LAST TERMINATOR CPI CR JNZ ERROR ; ERROR IF NOT CARRIAGE RETURN LXI B,0FFFFH ; HL GETS LARGEST NUMBER MOV A,L ; GET WHAT'S LEFT OF MAXIMUM ARG COUNT ORA A ; CHECK FOR 0 JZ GNM20 ; IF YES, 3 NUMBERS WERE INPUT GNM15: PUSH B ; IF NOT, FILL REMAINING ARGUMENTS WITH 0FFFFH DCR L JNZ GNM15 GNM20: POP B ; GET THE 3 ARGUMENTS OUT POP D POP H CALL HILO ; SEE IF FIRST >= SECOND ; FALSE GNM25 ; NO - BRANCH JNC GNM25 ; NO - BRANCH MOV D,H MOV E,L ; YES - MAKE SECOND EQUAL TO THE FIRST GNM25: XTHL ; PUT FIRST ON STACK - GET RETURN ADDR PUSH D ; PUT SECOND ON STACK PUSH B ; PUT THIRD ON STACK PUSH H ; PUT RETURN ADDRESS ON STACK GNM30: DCR A ; DECREMENT RESIDUAL COUNT RM ; IF NEGATIVE, PROPER RESULTS ON STACK POP H ; ELSE, GET RETURN ADDR XTHL ; REPLACE TOP RESULT WITH RETURN ADDR JMP GNM30 ; TRY AGAIN ; ; ;***************************************************************** ; ; ; FUNCTION: HILO ; INPUTS: DE - 16 BIT INTEGER ; HL - 16 BIT INTEGER ; OUTPUTS: CARRY - 0 IF HL=DE ; CALLS: NOTHING ; DESTROYS: A,F/F'S ; DESCRIPTION: HILO COMPARES THE 2 16 BIT INTEGERS IN HL AND DE. THE ; INTEGERS ARE TREATED AS UNSIGNED NUMBERS. THE CARRY ; BIT IS SET ACCORDING TO THE RESULT OF THE COMPARISON. ; HILO: PUSH B ; SAVE BC MOV B,A ; SAVE A REGISTER PUSH H ; SAVE HL PAIR MOV A,D ; CHECK FOR DE = 0000 ORA E JZ HIL05 ; WE`RE AUTOMATICALLY DONE IF IT IS INX H ; INCREMENT HL BY 1 MOV A,H ; WANT TO TEST FOR 0 RESULT AFTER ORA L ; /INCREMENTING JZ HIL05 ; IF SO, HL MUST HAVE CONTAINED 0FFFFH POP H ; IF NOT, RESTORE ORIGINAL HL PUSH D ; SAVE DE MVI A,0FFH ; Want TO TAKE 2`S COMPLEMENT OF DE CONTENTS XRA D ; MOV D,A ; MVI A,0FFH ; XRA E ; MOV E,A ; INX D ; 2`S COMPLEMENT ODE TO DE MOV A,L ; ADD E ; ADD HL AND DE MOV A,H ; ADC D ; THIS OPERATION SETS CARRY PROPERLY POP D ; RESTORE ORIGINAL DE CONTENTS MOV A,B ; RESTORE ORIGINAL CONTENTS OF A POP B ; RESTORE ORIGINAL CONTENTS OF BC RET ; RETURN WITH CARRY SET AS REQUIRED HIL05: POP H ; IF HL CONTAINS 0FFFFH, THEN CARRY CAN MOV A,B ; /Only BE WSET TO 1 POP B ; RESTORE ORIGINAL CONTENTS OF REGISTERS JMP SRET ; SET CARRY AND RETURN ; ; ;***************************************************************** ; ; ; FUNCTION: NMOUT ; INPUTS: A - 8 BIT INTEGER ; OUTPUTS: NONE ; CALLS: ECHO,PRVAL ; DESTROYS: A,B,C,F/F'S ; DESCRIPTION: NMOUT CONVERTS THE 8 BIT, UNSIGNED INTEGER IN THE ; A REGISTER INTO 2 ASCII CHARACTERS. THE ASCII CHARACTERS ; ARE THE ONES REPRESENTING THE 8 BITS. THESE TWO ; CHARACTERS ARE SENT TO THE CONSOLE AT THE CURRENT PRINT ; POSITION OF THE CONSOLE. ; NMOUT: PUSH H ; SAVE HL - DESTROYED BY PRVAL PUSH PSW ; SAVE ARGUMENT RRC RRC RRC RRC ; GET UPPER 4 BITS TO LOW 4 BIT POSITIONS ANI HCHAR ; MASK OUT UPPER 4 BITS - WANT 1 HEX CHAR MOV C,A ; CALL PRVAL ; CONVERT LOWER 4 BITS TO ASCII CALL ECHO ; SEND TO TERMINAL POP PSW ; GET BACK ARGUMENT ANI HCHAR ; MASK OUT UPPER 4 BITS - WANT 1 HEX CHAR MOV C,A ; CALL PRVAL ; CALL ECHO ; POP H ; RESTORE SAVED VALUE OF HL RET ; ; ;**************************************************************************** ; ; ; FUNCTION; PRVAL ; INPUTS: A - INTEGER, RANGE 0 TO F ; OUTPUTS: A - ASCII CHARACTER ; CALLS: NOTHING ; DESTROYS: B,C,H,L,F/F`S ; DESCRIPTION: PRVAL CONVERTS A NUMBER IN THE RANGE 0 TO F HEX TO ; THE CORRESPONDING ASCII CHARACTER, 0-9,A-F. PRVAL ; DOES NOT CHECK THE VALIDITY OF ITS INPUT ARGUMENT. ; PRVAL: LXI H,DIGTB ; ADDRESS OF TABLE MVI B,0 ; CLEAR HIGH ORDER BITS OF BC DAD B ; ADD DIGIT VALUE TO HL ADDRESS MOV C,M ; FETCH CHARACTER FROM MEMORY RET ; ; ;******************************************************************** ; ; ; FUNCTION: REGDS ; INPUTS: NONE ; OUTPUTS: NONE ; CALLS: ECHO,NMOUT,ERROR,CROUT ; DESTROYS: A,B,C,D,E,H,L,F/F'S ; DESCRIPTION: REGDS DISPLAYS THE CONTENTS OF THE REGISTER SAVE ; LOCATIONS, IN FORMATTED FORM, ON THE CONSOLE. THE ; DISPLAY IS DRIVEN FROM A TABLE, RTAB, WHICH CONTAINS ; THE REGISTER'S PRINT SYMBOL, SAVE LOCATION ADDRESS, ; AND LENGTH (8 OR 16 BITS). ; REGDS: LXI H,RTAB ; LOAD HL WITH ADDRESS OF START OF TABLE REG05: MOV C,M ; GET PRINT SYMBOL OF REGISTER MOV A,C ORA A ; TEST FOR 0 - END OF TABLE JNZ REG10 ; IF NOT END, BRANCH CALL CROUT ; ELSE, CARRIAGE RETURN/LINE FEED TO END RET ; /DISPLAY REG10: CALL ECHO ; ECHO CHARACTER MVI C,'=' CALL ECHO ; OUTPUT EQUALS SIGN, I.E. A= INX H ; POINT TO START OF SAVE LOCATION ADDRESS MOV E,M ; GET LSP OF SAVE LOCATION ADDRESS TO E MVI D,REGS SHR 8 ; PUT MSP OF SAVE LOC ADDRESS INTO D INX H ; POINT TO LENGTH FLAG LDAX D ; GET CONTENTS OF SAVE ADDRESS CALL NMOUT ; DISPLAY ON CONSOLE MOV A,M ; GET LENGTH FLAG ORA A ; SET SIGN F/F JZ REG15 ; IF 0, REGISTER IS 8 BITS DCX D ; ELSE, 16 BIT REGISTER SO MORE TO DISPLAY LDAX D ; GET LOWER 8 BITS CALL NMOUT ; DISPLAY THEM REG15: MVI C,' ' CALL ECHO ; OUTPUT BLANK CHARACTER INX H ; POINT TO START OF NEXT TABLE ENTRY JMP REG05 ; DO NEXT REGISTER ; ; ;*************************************************************************** ; ; ; FUNCTION: RGADR ; INPUTS: C - CHARACTER DENOTING REGISTER ; OUTPUTS: BC - ADDRESS OF ENTRY IN RTAB CORRESPONDING TO REGISTER ; CALLS: ERROR ; DESTROYS: A,B,C,D,E,H,L,F/F'S ; DESCRIPTION: RGADR TAKES A SINGLE CHARACTER AS INPUT. THIS CHARACTER ; DENOTES A REGISTER. RGADR SEARCHES THE TABLE RTAB ; FOR A MATCH ON THE INPUT ARGUMENT. IF ONE OCCURS, ; RGADR RETURNS THE ADDRESS OF THE ADDRESS OF THE ; SAVE LOCATION CORRESPONDING TO THE REGISTER. THIS ; ADDRESS POINTS INTO RTAB. IF NO MATCH OCCURS, THEN ; THE REGISTER IDENTIFIER IS ILLEGAL AND CONTROL IS ; PASSED TO THE ERROR ROUTINE. ; RGADR: LXI H,RTAB ; HL GETS ADDRESS OF TABLE START LXI D,RTABS ; DE GET SIZE OF A TABLE ENTRY RGA05: MOV A,M ; GET REGISTER IDENTIFIER ORA A ; CHECK FOR TABLE END (IDENTIFIER IS 0) JZ ERROR ; IF AT END OF TABLE, ARGUMENT IS ILLEGAL CMP C ; ELSE, COMPARE TABLE ENTRY AND ARGUMENT JZ RGA10 ; IF EQUAL, WE'VE FOUND WHAT WE'RE LOOKING FOR DAD D ; ELSE, INCREMENT TABLE POINTER TO NEXT ENTRY JMP RGA05 ; TRY AGAIN RGA10: INX H ; IF A MATCH, INCREMENT TABLE POINTER TO MOV B,H ; /SAVE LOCATION ADDRESS MOV C,L ; RETURN THIS VALUE RET ; ; ;***************************************************************** ; ; ; FUNCTION: RSTTF ; INPUTS: NONE ; OUTPUTS: NONE ; CALLS: NOTHING ; DESTROYS: A,B,C,D,E,H,L,F/F'S ; DESCRIPTION: RSTTF RESTORES ALL CPU REGISTER, FLIP/FLOPS, STACK ; POINTER AND PROGRAM COUNTER FROM THEIR RESPECTIVE ; SAVE LOCATIONS IN MEMORY. THE ROUTINE THEN TRANSFERS ; CONTROL TO THE LOCATION SPECIFIED BY THE PROGRAM ; COUNTER (I.E. THE RESTORED VALUE). THE ROUTINE ; EXITS WITH THE INTERRUPTS ENABLED. ; RSTTF: DI ; DISABLE INTERRUPTS WHILE RESTORING THINGS LXI H,MSTAK ; SET MONITOR STACK POINTER TO START OF STACK SPHL ; POP D ; START ALSO END OF REGISTER SAVE AREA POP B ; POP PSW ; LHLD SSAVE ; RESTORE USER STACK POINTER SPHL ; LHLD PSAVE ; PUSH H ; PUT USER RETURN ADDRESS ON USER STACK LHLD LSAVE ; RESTORE HL REGISTERS EI ; ENABLE INTERRUPTS NOW RET ; JUMP TO RESTORED PC LOCATION ; ; ;***************************************************************** ; ; ; FUNCTION: SRET ; INPUTS: NONE ; OUTPUTS: CARRY = 1 ; CALLS: NOTHING ; DESTROYS: CARRY ; DESCRIPTION: SRET IS JUMPED TO BY ROUTINES WISHING TO RETURN SUCCESS. ; SRET SETS THE CARRY TRUE AND THEN RETURNS TO THE ; CALLER OF THE ROUTINE INVOKING SRET. ; SRET: STC ; SET CARRY TRUE RET ; RETURN APPROPRIATELY ; ; ;***************************************************************** ; ; ; FUNCTION: STHF0 ; INPUTS: DE - 16 BIT ADDRESS OF BYTE TO BE STORED INTO ; OUTPUTS: NONE ; CALLS: NOTHING ; DESTROYS: A,B,C,H,L,F/F'S ; DESCRIPTION: STHF0 CHECKS THE HALF BYTE FLAG IN TEMP TO SEE IF ; IT IS SET TO LOWER. IF SO, STHF0 STORES A 0 TO ; PAD OUT THE LOWER HALF OF THE ADDRESSED BYTE; ; OTHERWISE, THE ROUTINE TAKES NO ACTION. ; STHF0: LDA TEMP ; GET HALF BYTE FLAG ORA A ; SET F/F'S RNZ ; IF SET TO UPPER, DON'T DO ANYTHING MVI C,0 ; ELSE, WANT TO STORE THE VALUE 0 CALL STHLF ; DO IT RET ; ; ;***************************************************************** ; ; ; FUNCTION: STHLF ; INPUTS: C - 4 BIT VALUE TO BE STORED IN HALF BYTE ; DE - 16 BIT ADDRESS OF BYTE TO BE STORED INTO ; OUTPUTS: NONE ; CALLS: NOTHING ; DESTROYS: A,B,C,H,L,F/F'S ; DESCRIPTION: STHLF TAKES THE 4 BIT VALUE IN C AND STORES IT IN ; HALF OF THE BYTE ADDRESSED BY REGISTERS DE. THE ; HALF BYTE USED (EITHER UPPER OR LOWER) IS DENOTED ; BY THE VALUE OF THE FLAG IN TEMP. STHLF ASSUMES ; THAT THIS FLAG HAS BEEN PREVIOUSLY SET ; (NOMINALLY BY ICMD). ; STHLF: PUSH D POP H ; MOVE ADDRESS OF BYTE INTO HL MOV A,C ; GET VALUE ANI 0FH ; FORCE TO 4 BIT LENGTH MOV C,A ; PUT VALUE BACK LDA TEMP ; GET HALF BYTE FLAG ORA A ; CHECK FOR LOWER HALF JNZ STH05 ; BRANCH IF NOT MOV A,M ; ELSE, GET BYTE ANI 0F0H ; CLEAR LOWER 4 BITS ORA C ; OR IN VALUE MOV M,A ; PUT BYTE BACK RET STH05: MOV A,M ; IF UPPER HALF, GET BYTE ANI 0FH ; CLEAR UPPER 4 BITS MOV B,A ; SAVE BYTE IN B MOV A,C ; GET VALUE RRC RRC RRC RRC ; ALIGN TO UPPER 4 BITS ORA B ; OR IN ORIGINAL LOWER 4 BITS MOV M,A ; PUT NEW CONFIGURATION BACK RET ; ; ;***************************************************************** ; ; ; FUNCTION: VALDG ; INPUTS: C - ASCII CHARACTER ; OUTPUTS: CARRY - 1 IF CHARACTER REPRESENTS VALID HEX DIGIT ; - 0 OTHERWISE ; CALLS: NOTHING ; DESTROYS: A,F/F'S ; DESCRIPTION: VALDG RETURNS SUCCESS IF ITS INPUT ARGUMENT IS ; AN ASCII CHARACTER REPRESENTING A VALID HEX DIGIT ; (0-9,A-F), AND FAILURE OTHERWISE. ; VALDG: MOV A,C CPI '0' ; TEST CHARACTER AGAINST '0' JM FRET ; IF ASCII CODE LESS, CANNOT BE VALID DIGIT CPI '9' ; ELSE, SEE IF IN RANGE '0'-'9' JM SRET ; CODE BETWEEN '0' AND '9' JZ SRET ; CODE EQUAL '9' CPI 'A' ; NOT A DIGIT - TRY FOR A LETTER JM FRET ; NO - CODE BETWEEN '9' AND 'A' CPI 'G' JP FRET ; NO - CODE GREATER THAN 'F' JMP SRET ; OKAY - CODE IS 'A' TO 'F', INCLUSIVE ; ; ;********************************************************************** ; ; ; FUNCTION: VALDL ; INPUTS: C - CHARACTER ; OUTPUTS: CARRY - 1 IF INPUT ARGUMENT VALID DELIMTER ; - 0 OTHERWISE ; CALLS: NOTHING ; DESTROYS: A,F/F'S ; DESCRIPTION: VALDL RETURNS SUCCESS IF ITS INPUT ARGUMENT IS A VALID ; DELIMITER CHARACTER (SPACE, COMMA, CARRIAGE RETURN) AND ; FAILURE OTHERWISE. ; VALDL: MOV A,C CPI ',' ; CHECK FOR COMMA JZ SRET CPI CR ; CHECK FOR CARRIAGE RETURN JZ SRET CPI ' ' ; CHECK FOR SPACE JZ SRET JMP FRET ; ERROR IF NONE OF THE ABOVE ; ; ;***************************************************************** ; ; MONITOR TABLES ; ;***************************************************************** ; ; SGNON: ; SIGNON MESSAGE DB CR,LF,'MCS-80 KIT',CR,LF LSGNON EQU $-SGNON ; LENGTH OF SIGNON MESSAGE ; CADR: ; TABLE OF ADDRESSES OF COMMAND ROUTINES DW 0 ; DUMMY DW XCMD DW SCMD DW MCMD DW ICMD DW GCMD DW DCMD ; CTAB: ; TABLE OF VALID COMMAND CHARACTERS DB 'D' DB 'G' DB 'I' DB 'M' DB 'S' DB 'X' NCMDS EQU $-CTAB ; NUMBER OF VALID COMMANDS ; DIGTB: DB '0' DB '1' DB '2' DB '3' DB '4' DB '5' DB '6' DB '7' DB '8' DB '9' DB 'A' DB 'B' DB 'C' DB 'D' DB 'E' DB 'F' ; RTAB: ; TABLE OF REGISTER INFORMATION DB 'A' ; REGISTER IDENTIFIER DB ASAVE AND 0FFH ; ADDRESS OF REGISTER SAVE LOCATION DB 0 ; LENGTH FLAG - 0=8 BITS, 1=16 BITS RTABS EQU $-RTAB ; SIZE OF AN ENTRY IN THIS TABLE DB 'B' DB BSAVE AND 0FFH DB 0 DB 'C' DB CSAVE AND 0FFH DB 0 DB 'D' DB DSAVE AND 0FFH DB 0 DB 'E' DB ESAVE AND 0FFH DB 0 DB 'F' DB FSAVE AND 0FFH DB 0 DB 'H' DB HSAVE AND 0FFH DB 0 DB 'L' DB LSAVE AND 0FFH DB 0 DB 'M' DB HSAVE AND 0FFH DB 1 DB 'P' DB PSAVE+1 AND 0FFH DB 1 DB 'S' DB SSAVE+1 AND 0FFH DB 1 DB 0 ; END OF TABLE MARKERS DB 0 ; ORG BRTAB ; JMP CO ; BRANCH TABLE FOR USER ACCESIBLE ROUTINES JMP CI ; ; ; ;***************************************************************** ; ; ORG DATA ORG REGS ; ORG TO REGISTER SAVE - STACK GOES IN HERE ; MSTAK EQU $ ; START OF MONITOR STACK ESAVE: DB 0 ; E REGISTER SAVE LOCATION DSAVE: DB 0 ; D REGISTER SAVE LOCATION CSAVE: DB 0 ; C REGISTER SAVE LOCATION BSAVE: DB 0 ; B REGISTER SAVE LOCATION FSAVE: DB 0 ; FLAGS SAVE LOCATION ASAVE: DB 0 ; A REGISTER SAVE LOCATION LSAVE: DB 0 ; L REGISTER SAVE LOCATION HSAVE: DB 0 ; H REGISTER SAVE LOCATION PSAVE: DW 0 ; PGM COUNTER SAVE LOCATION SSAVE: DW 0 ; USER STACK POINTER SAVE LOCATION TEMP: DB 0 ; TEMPORARY MONITOR CELL ; ORG BRLOC ; ORG TO USER BRANCH LOCATION ; USRBR: DS 3 ; BRANCH GOES IN HERE ; ; END