; ; EDUCATOR-8080 ; ;Originally written by the Digital Group ;Converted to run on CP/M BY Keith Petersen, ;W8SDZ, July 28, 1980. ; BKSPC EQU 08H ;BACKSPACE CR EQU 0DH ;CARRIAGE RETURN LF EQU 0AH ;LINE FEED CLR EQU 1AH ;SCREEN CLEAR CHARACTER DEL EQU 7FH ;DELETE (RUBOUT) ; ORG 100H ; ;THE CONTROL ROUTINE IS THE TOP OF THE STRUCTURE AND ;CONTROLS THE OPERATION OF THE ENTIRE PROGRAM. ; CNTRL: LXI SP,STACK ;SET STACK POINTER LHLD 1 ;GET CBIOS POINTER LXI D,3 ;READY FOR DAD DAD D ;CONSTAT DAD D ;CONIN SHLD VCONIN+1 ;MODIFY CALL ADDRESS DAD D ;CONOUT SHLD VCONOUT+1 ;MODIFY CALL ADDRESS ; NOTZER: CALL DSPLY ;DISPLAY CONTENTS OF REGISTERS CALL CMDNT ;ENTER A COMMAND CALL FETCH ;FETCH THE CORRECT OPCODE ORA A ;SET ZERO FLAG AS PER CONTENTS JNZ NOTZER ;JUMP IF NOT ZERO ERROR OCCURED CALL XQTER ;GO EXECUTE THE CURRENT COMMAND JMP NOTZER ;LOOP FOREVER ; ;THIS DISPLAY ROUTINE CONTROLS THE GENERATION OF THE DYNAMIC ;DISPLAY. ; DSPLY: LXI H,TITLS ;LOAD ADDRESS OF TITLES INTO HL CALL CHEDT ;DISPLAY TITLES LXI H,BLINE ;LOAD ADDR OF BLINE TITLE LDA BREG ;LOAD CONTENTS OF BREG INTO A CALL DSPCV ;CONVERT AND DISPLAY LXI H,CLINE ;LOAD ADDR OF CLINE TITLE LDA CREG ;LOAD CONTENTS OF CREG INTO A CALL DSPCV ;CONVERT AND DISPLAY LXI H,AFHDR ;LOAD ADDR OF A FLAGS TITLE CALL CHEDT ;DISPLAY TITLES LHLD PSWA ;LOAD FLAGS AND A INTO HL MOV A,L ;MOVE FLAGS TO A ANI 4 ;AND OFF ALL BUT PARITY FLAG CALL DSPFG ;DISPLAY THE FLAG VALUE MOV A,L ;MOVE FLAGS TO A ANI 40H ;AND OFF ALL BUT ZERO FLAG CALL DSPFG ;DISPLAY THE FLAG VALUE MOV A,L ;MOVE FLAGS TO A ANI 80H ;AND OFF ALL BUT SIGN FLAG CALL DSPFG ;DISPLAY THE FLAG VALUE MOV A,L ;MOVE FLAGS TO A ANI 10H ;AND OFF ALL BUT AUX. CARRY FLAG CALL DSPFG ;DISPLAY THE FLAG VALUE MOV A,L ;MOVE FLAGS TO A ANI 1 ;AND OFF ALL BUT CARRY FLAG CALL DSPFG ;DISPLAY THE FLAG VALUE MOV A,H ;MOVE A REGISTER VALUE TO A CALL DSPCN ;DISPLAY WITH NO TITLE PRINT RET ;RETURN TO THE CNTRL ROUTINE ; ;THE DISPLAY CONVERSION ROUTINE PRINTS BINARY, ;OCTAL AND HEXADECIMAL. ; DSPCV: PUSH PSW ;SAVE OUTPUT VALUE FOR CHEDT CALL CHEDT ;DISPLAY LINE TITLE ADDR IN HL POP PSW ;RETRIEVE SAVED OUTPUT VALUE ; DSPCN: MVI E,8 ;MOVE 8 TO E REGISTER ; DSPBT: RLC ;ROTATE MSB INTO CARRY AND LSB PUSH PSW ;SAVE CURRENT VALUE ANI 1 ;AND OFF ALL BUT LSB CALL DSPFG ;GO DISPLAY BIT VALUE POP PSW ;RETRIEVE SAVED CURRENT VALUE DCR E ;DECREMENT LOOP COUNT JNZ DSPBT ;JUMP IF LOOP COUNT NOT ZERO ORA A ;RESET CARRY MVI E,3 ;MOVE 3 TO E REGISTER ; DSPQT: RAL ;MSB TO CARRY, CARRY TO LSB RAL ;DO IT AGAIN, RAL ; THREE TIMES FOR OCTAL DIGIT PUSH PSW ;SAVE CURRENT VALUE ANI 7 ;AND OFF ALL BUT OCTAL LSD ORI '0' ;MAKE ASCII CALL CHRPR ;OUTPUT THE CHARACTER POP PSW ;RETRIEVE SAVED CURRENT VALUE DCR E ;DECREMENT LOOP COUNT JNZ DSPQT ;JUMP IF LOOP COUNT NOT ZERO CALL DSPSP ;OUTPUT A SPACE MVI E,2 ;MOVE 2 TO E ; DSPHT: RLC ;ROTATE MSB INTO CARRY AND LSB RLC ;DO IT AGAIN RLC ; FOUR TIMES FOR RLC ; HEXADECIMAL SHIFT PUSH PSW ;SAVE CURRENT VALUE ANI 0FH ;AND OFF ALL BUT HEX LSD ADI '0' ;ADD ON BITS TO MAKE ASCII CPI '9'+1 ;COMPARE RESULT TO ONE MORE THAN 9 JC DSPHS ;IF NUMERIC THEN SKIP ADJUSTMENT ADI 7 ;ADD 7 GIVING ASCII A-F CODES ; DSPHS: CALL CHRPR ;OUTPUT THE CHARACTER POP PSW ;RETRIEVE SAVED CURRENT VALUE NOP DCR E ;DECREMENT LOOP COUNT JNZ DSPHT ;JUMP IF LOOP COUNT NOT ZERO RET ;RETURN TO CALLING ROUTINE ; ;DISPLAY FLAG OR BINARY DIGIT FOLLOWED BY A SPACE. ALTERNATE ;ENTRY IS USED TO DISPLAY A SPACE. ; DSPFG: JZ DSPFZ ;JUMP IF PASSED VALUE IS A ZERO MVI A,1 ;OTHERWISE MOVE A 1 INTO A ; DSPFZ: ADI '0' ;CONVERT INTO ASCII NUMERIC CHAR. CALL CHRPR ;OUTPUT THE CHARACTER ; DSPSP: PUSH PSW ;SAVE THE FLAGS AND VALUE IN A MVI A,' ' ;MOVE SPACE INTO A CALL CHRPR ;OUTPUT THE SPACE POP PSW ;RETRIEVE THE SAVED FLAGS AND A RET ;RETURN TO THE CALLING ROUTINE ; ;THE CHARACTER STRING OUTPUT EDIT ROUTINE. ; CHEDT: MOV A,M ;MOVE NEXT CHARACTER INTO A CPI 80H ;COMPARE IT TO 200 OCTAL RZ ;RETURN IF EQUAL IT'S END OF STRING JNC CHSPA ;JUMP IF GREATER FOR SPACE ROUTINE CALL CHRPR ;ELSE GO OUTPUT THE CHARACTER ; CHEND: INX H ;INCREMENT THE STRING INDEX JMP CHEDT ;LOOP FOR NEXT CHARACTER ; CHSPA: SUI 80H ;SUBTRACT 200 OCTAL FROM VALUE MOV B,A ;MOVE SPACE COUNT TO B ; CHSPL: MVI A,' ' ;MOVE SPACE INTO A CALL CHRPR ;OUTPUT THE SPACE DCR B ;DECREMENT SPACE COUNT JNZ CHSPL ;JUMP IF COUNT NOT ZERO TO START OF LOOP JMP CHEND ;JUMP BACK INTO CHEDT LOOP ; ;THE COMMAND ENTRY ROUTINE ACCEPTS INPUT FROM THE KEYBOARD ;FOR COMMANDS. ; CMDNT: LXI H,CMDMS ;MOVE ADDRESS OF COMMAND? INTO HL CALL CHEDT ;DISPLAY THE MESSAGE LXI H,CMDAR ;MOVE ADRS OF COMMAND INPUT AREA HL MVI B,22 ;MOVE MAXIMUM LENGTH TO B ; CMDKB: CALL KEYBD ;GET AN INPUT CHARACTER CPI 'L'-40H ;IS IT A CONTROL-L LINE DELETE? JZ CNTRL ;IF SO THEN RESTART PROGRAM CPI CR ;IS IT A CARRIAGE RETURN? JZ CMDND ;IF SO THEN GO COMPRESS INPUT CPI DEL ;IS IT A DELETE CHARACTER? JNZ CMDST ;IF NOT THEN GO STORE THE CHARACTER MVI A,BKSPC ;IF SO REPLACE WITH BACKSPACE ; CMDST: MOV M,A ;STORE INPUT CHAR. IN COMMAND BUFFER CALL CHRPR ;DISPLAY THE INPUT CHARACTER INX H ;INCREMENT COMMAND WORK AREA INDEX DCR B ;DECREMENT COMMAND LENGTH COUNT JNZ CMDKB ;IF NOT FULL THEN REITERATE MVI A,1 ;IF BUFFER FULL THEN SELECT ERROR CALL ERROR ; NUMBER 1 AND PRINT ITS MSG. JMP CNTRL ;RESTART THE PROGRAM ; ;THE COMMAND COMPRESS ROUTINE ELIMINATES ALL BUT LETTERS ;AND NUMBERS. ; CMDND: LXI H,CMDAR ;LOAD HL WITH ADRS OF WORK AREA PUSH H ;PUSH & POP MOVE IT TO DE POP D ; AS THE COMPRESSION POINTER MVI A,22 ;LOAD A WITH MAXIMUM LENGTH SUB B ;SUBTRACT REMAINING LENGTH FROM B MOV B,A ;MOVE ACTUAL LENGTH TO B ; CMDNX: MOV A,M ;MOVE COMMAND CHARACTER TO A CPI BKSPC ;IS IT BACKSPACE? JNZ CMDCH ;IF NOT THEN GO TO OTHER TESTS MVI A,CMDAR AND 0FFH ;LOW ADRS BYTE OF CMDAR TO A CMP E ;COMPARE TO CURRENT LOW ADRS BYTE JNC CMDNS ;IF NOT GREATER THEN SKIP SAVE DCX D ;ELSE BACK UP COMPRESSION POINTER JMP CMDNS ;SKIP SAVING THE CHARACTER ; CMDCH: CPI '0' ;IS THE CHARACTER LESS THAN '0'? JC CMDNS ;IF SO THEN SKIP SAVING IT CPI '9'+1 ;IS THE CHARACTER LESS THAN '9'+1? JC CMDSV ;IF SO THEN SAVE NUMERIC VALUE CPI 'A' ;IS THE CHARACTER LESS THAN 'A'? JC CMDNS ;IF SO THEN SKIP SAVING IT CPI 'Z'+1 ;IS THE CHARACTER GREATER THAN 'Z'? JNC CMDNS ;IF SO THEN SKIP SAVING IT ; CMDSV: STAX D ;STORE CHARACTER IN COMPRESSED AREA INX D ;INCREMENT COMPRESSION POINTER INDEX ; CMDNS: INX H ;INCREMENT INPUT STRING POINTER DCR B ;DECREMENT ACTUAL LENGTH COUNT JNZ CMDNX ;IF LENGTH IS NOT ZERO THEN REITERATE RET ;ELSE RETURN TO CNTRL CALLING POINT ; ;THE FETCH INSTRUCTION/COMMAND ROUTINE VALIDATES AND BUILDS THE ;OBJECT CODE. ; FETCH: LXI H,OPTAB ;LOAD ADDRESS OF OPCODE TABLE HL MVI E,31 ;MOVE TABLE ELEMENT COUNT TO E ; FLOOP: PUSH H ;SAVE CURRENT ELEMENT ADDRESS LXI B,CMDAR ;LOAD ADDRESS OF CMDAR INTO BC MVI D,3 ;MOVE OPCODE LENGTH TO D ; FCOMP: LDAX B ;LOAD COMMAND CHARACTER TO A INDEXED BY B CMP M ;COMPARE IT TO TABLE CHARACTER JNZ FNXEL ;IF NOT EQUAL THEN GO TO NEXT ELEMENT INX B ;INCREMENT COMMAND CHARACTER INDEX INX H ;INCREMENT TABLE CHARACTER INDEX DCR D ;DECREMENT OPCODE LENGTH COUNTER JNZ FCOMP ;IF NOT ZERO CONTINUE TEST LOOP XTHL ;EXCHANGE HL WITH TOP OF STACK POP H ;POP HL FROM STACK TO CLEAR IT MOV E,M ;MOVE NAKED OPCODE TO E,D IS ZERO PUSH D ;SAVE NAKED OPCODE INX H ;INCREMENT TABLE POINTER MOV E,M ;DECODE ROUTINE LOW ADDRESS BYTE TO E INX H ;INCREMENT TABLE POINTER MOV D,M ;DECODE ROUTINE HIGH ADDRESS BYTE TO D XCHG ;MOVE DECODE ROUTINE ADDRESS TO HL POP D ;UNSAVE NAKED OPCODE TO DE XRA A ;CLEAR A, NO ERROR CODE PCHL ;JUMP TO ADDRESS OF DECODE ROUTINE ; FNXEL: LXI B,6 ;LOAD DOUBLE LENGTH 6 INTO BC POP H ;UNSAVE CURRENT ELEMENT ADDRESS DAD B ;ADD 6 TO IT DCR E ;DECREMENT TABLE ELEMENT COUNT JNZ FLOOP ;REITERATE TO TEST NEXT ELEMENT MVI A,2 ;MOVE ERROR CODE 2 TO A JMP ERROR ;GO DISPLAY ERROR 2, OPCODE UNKNOWN NOP ;NO OPERATION FILLER ; ;THE INSTRUCTION DECODER ROUTINES FOLLOW ;INSTRUCTIONS USING THE DIRCT ROUTINE REQUIRE NO DECODING. ;EXAMPLE: RAL, CMA, ETC. ; DIRCT: RET ;RETURN TO CNTRL FOR EXECUTION ; ;THE MOVRT IS USED ONLY BE THE MOV COMMAND ; MOVRT: CALL RG543 ;VALIDATE DESTINATION REGISTER ORA A ;SET FLAGS BASED ON A CONTENTS RNZ ;RETURN NOT ZERO WITH ERROR ; ;INSTRUCTIONS USING THE RG210 ROUTINE REQUIRE A SOURCE REGISTER ; RG210: LDAX B ;LOAD NEXT COMMAND CHARACTER INTO A INX B ;INCREMENT COMMAND CHARACTER INDEX CALL REGAN ;ANALYZE FOR VALID REGISTER JNC RGERR ;IF CY=0 THEN REGISTER NOT VALID ADD E ;ADD NAKED OPCODE TO REGISTER VALUE MOV E,A ;MOVE RESULT BACK TO E XRA A ;CLEAR A INDICATING NO ERRORS RET ;RETURN TO CNTRL ; ;THE REGISTER ERROR ROUTINE IS USED TO INDICATE REGISTER ;DESIGNATION ERRORS ; RGERR: MVI A,3 ;MOV ERROR CODE 3 TO A JMP ERROR ;GO DISPLAY ERROR 3, INVALID REGISTER ; ;THE REGISTER ANALYSIS AND VALIDATION ROUTINE IS USED BY RG543, ;RG210, AND RG54B ; REGAN: SUI 'A' ;SUBTRACT AN 'A' FROM THE CHARACTER CPI 3 ;COMPARE THE RESULT TO 3 RNC ;IF NOT LESS THAN 3 RETURN WITH CY=0 DCR A ;DECREMENT RESULT: A=377,B=000,C=001 ANI 7 ;AND OFF ALL BUT OCTAL LSD STC ;SET CY=1 INDICATING NO ERROR RET ;RETURN TO CALLING ROUTINE ; ;THE MVIRT IS USED ONLY BY THE MVI COMMAND ; MVIRT: CALL RG543 ;VALIDATE DESTINATION REGISTER ORA A ;SET FLAGS BASED ON A CONTENTS RNZ ;RETURN NOT ZERO WITH ERROR ; ;INSTRUCTIONS REQUIRING AN IMMEDIATE OPERAND USE THE IMMED ;ROUTINE ; IMMED: LDAX B ;LOAD NEXT COMMAND CHARACTER INTO A INX B ;INCREMENT COMMAND CHARACTER INDEX CPI 'B' ;IS THE CMND CHAR. A 'B' ? JZ BINRY ;IF SO THEN PROCESS AS BINARY CPI 'Q' ;IS THE COMMAND CHARACTER A 'Q'? JZ OCTAL ;IF SO THEN PROCESS AS OCTAL CPI 'H' ;IS THE CMND CHAR. AN 'H' ? JZ HEX ;IF SO THEN PROCESS AS HEXADECIMAL CPI '8' ;IS THE COMMAND CHARACTER LESS THAN '8'? JC OCTAD ;IF SO THEN TREAT AS OCTAL MVI A,5 ;MOVE ERROR CODE 5 TO A JMP ERROR ;GO DISPLAY ERROR 5, INVALID IMMEDIATE ; ;INSTRUCTIONS USING THE RG543 ROUTINE REQUIRE A DESTINATION ;REGISTER ; RG543: LDAX B ;LOAD NEXT COMMAND CHARACTER INTO A INX B ;INCREMENT COMMAND CHARACTER INDEX CALL REGAN ;ANALYZE FOR VALID REGISTER JNC RGERR ;IF CY=0 THEN REGISTER NOT VALID RLC ;SHIFT OCTAL REGISTER VALUE RLC ;LEFT THREE RLC ; PLACES ADD E ;ADD NAKED OPCODE TO SHIFTED VALUE MOV E,A ;MOVE RESULT BACK TO E XRA A ;CLEAR A INDICATING NO ERRORS RET ;RETURN TO CALLING ROUTINE ; ;INSTRUCTIONS USING THE RG54B ROUTINE ARE INX AND DCX ; RG54B: LDAX B ;LOAD NEXT COMMAND CHARACTER INTO A INX B ;INCREMENT COMMAND CHARACTER INDEX CALL REGAN ;ANALYZE FOR VALID REGISTER CPI 0 ;IS THE REGISTER A ZERO? RZ ;IF SO IT'S 'B' SO RETURN MVI A,4 ;MOVE ERROR CODE 4 TO A JMP ERROR ;GO DISPLAY ERROR 4, INVALID REGISTER ; ;THE BINARY ROUTINE CONVERTS A BINARY IMMEDIATE VALUE INTO ;USABLE FORM ; BINRY: MVI H,8 ;MOVE 8 TO H FOR COUNT ; BLOOP: LDAX B ;LOAD NEXT COMMAND CHARACTER INTO A SUI '0' ;SUBTRACT A '0' FROM IT CPI 2 ;IS THE RESULT LESS THAN 2? JNC IMMER ;IF NOT THEN GO DISPLAY IMMEDIATE ERROR PUSH H ;SAVE THE COUNT MOV L,D ;MOVE D TO L (IMMEDIATE BYTE) DAD H ;SHIFT HL LEFT ONE BIT ADD L ;ADD L TO BIT IN A MOV D,A ;MOVE THE RESULT BACK TO D POP H ;UNSAVE THE COUNT INX B ;INCREMENT COMMAND CHARACTER INDEX DCR H ;DECREMENT THE COUNT JNZ BLOOP ;IF NOT ZERO THEN REITERATE XRA A ;CLEAR A INDICATING NO ERRORS RET ;RETURN TO CNTRL ; ;THE IMMEDIATE ERROR ROUTINE IS USED TO INDICATE IMMEDIATE VALUE ;ERRORS ; IMMER: MVI A,6 ;MOVE ERROR CODE 3 TO A JMP ERROR ;GO DISPLAY ERROR 3, INVALID IMMEDIATE ; ;THE OCTAD ENTRY POINT TO THE OCTAL ROUTINE IS FOR THE DEFAULT ;CONDITION ; OCTAD: DCX B ;DECREMENT COMMAND CHARACTER INDEX ; ;THE OCTAL ROUTINE CONVERTS AN OCTAL IMMEDIATE VALUE INTO ;USABLE FORM ; OCTAL: MVI H,3 ;MOVE A 3 INTO H FOR COUNT ; OLOOP: LDAX B ;LOAD NEXT COMMAND CHARACTER INTO A SUI '0' ;SUBTRACT A '0' FROM IT CPI 8 ;IS CMND LESS THAN 8? JNC IMMER ;IF NOT GO DISP IMMED ERROR PUSH H ;SAVE THE COUNT MOV L,D ;MOVE D TO L IMMED BYTE DAD H ;SHIFT IMMEDIATE DAD H ; BYTE LEFT DAD H ; THREE BITS ADD L ;ADD L TO VALUE IN A MOV D,A ;MOVE RESULT BACK TO D POP H ;UNSAVE THE COUNT INX B ;INCREMENT COMND CHAR INDEX DCR H ;DECREMENT THE COUNT JNZ OLOOP ;IF NOT ZERO THEN REITERATE XRA A ;CLEAR A INDICATING NO ERRORS RET ;RETURN TO CNTRL ; ;THE HEX ROUTINE COVERTS A HEXADECIMAL IMMEDIATE VALUE INTO ;USABLE FORM. ; HEX: MVI H,2 ;MOVE A 2 INTO H FOR COUNT ; HLOOP: LDAX B ;LOAD NEXT CMND CHAR INTO A SUI '0' ;SUBTRACT '0' FROM IT CPI 9+1 ;IS IT LESS THAN '9'+1? JC HCHOK ;IF SO THEN NUMERIC CHARACTER IS OK SUI 7 ;ELSE CONVERT ALPHABETIC TO NUMERIC CPI 15+1 ;IS CHARACTER VALUE GREATER THAN 15? JNC IMMER ;IF SO THAN INVALID HEXADECIMAL VALUE ; HCHOK: PUSH H ;SAVE THE COUNT MOV L,D ;MOVE D TO L IMMEDIATE BYTE DAD H ;SHIFT IMMEDIATE DAD H ; BYTE LEFT DAD H ; FOUR DAD H ; BITS ADD L ;ADD L TO VALUE IN A MOV D,A ;MOVE RESULT BACK TO D POP H ;UNSAVE THE COUNT INX B ;INCREMENT COMMAND CHARACTER INDEX DCR H ;DECREMENT THE COUNT JNZ HLOOP ;IF NOT ZERO THAN REITERATE XRA A ;CLEAR A INDICATING NO ERRORS RET ;RETURN TO CNTRL ; ;THE XQTER ROUTINE EXECUTES THE GENERATED OBJECT CODE FOR ;EDUCATOR 8080 ; XQTER: XCHG ;MOVE GENERATED OPCODE TO HL SHLD XQTOP ;STORE IT AT EXECUTION POINT LHLD PSWA ;LOAD WORKING PSW & A INTO HL PUSH H ;PUSH & POP SETS VALUES FOR POP PSW ; WORKING REGISTER AND FLAGS LHLD BANDC ;LOAD WORKING B AND C INTO HL PUSH H ;PUSH & POP SETS VALUES FOR POP B ; WORKING B AND C REGISTERS ; XQTOP: NOP ;THE COMMAND TO BE EXECUTED NOP ;IMMEDIATE VALUE OR NOP PUSH B ;PUSH B AND C WORKING REGISTER VALUES POP H ;POP THEM INTO HL SHLD BANDC ;STORE THEM IN SAVE AREA PUSH PSW ;PUSH PSW AND A WORKING VALUES POP H ;POP THEM INTO HL SHLD PSWA ;STORE THEM IN SAVE AREA RET ;RETURN TO CNTRL FOR NEXT COMMAND ; ;THE ERROR ROUTINE IS USED TO DISPLAY ERROR MESSAGES ; ERROR: PUSH PSW ;SAVE ERROR CODE IN A LXI H,ERRSP ;LOAD ADDRESS OF ERROR HEADER SPACES CALL CHEDT ;GO OUTPUT ERROR HEADER SPACES POP PSW ;UNSAVE ERROR CODE LXI H,ERTAB ;LOAD ADDRESS OF ERROR MESSAGE TABLE ADD L ;ADD LOW ADDRESS BYTE TO ERROR CODE MOV L,A ;MOVE RESULT TO L, POINTS TO OFFSET MOV L,M ;MOVE OFFSET TO L ; ;NOTE: HL NOW CONTAINS THE ADDRESS OR THE ERROR MESSAGE ; CALL CHEDT ;OUTPUT THE ERROR MESSAGE ; ERTIM: LXI D,0 ;LOAD DE WITH TIMING LOOP VALUE DCR E ;DECREMENT VALUE IN E 256 TIMES JNZ ERTIM+1 ;REITERATE LOOP 256 TIMES ; ;THE ABOVE JMP GOES TO THE FIRST 000 IN THE LXI COMMAND WHICH ;IS AN EFFECTIVE NOP ; DCR D ;DECREMENT D JNZ ERTIM+1 ;REITERATE OUTER LOOP 256 TIMES MVI A,0FFH ;MOVE A 377 TO A INDICATING ERROR RET ;RETURN TO CNTRL ; OPTAB: DB 'ACI',0CEH DW IMMED DB 'ADC',88H DW RG210 DB 'ADD',80H DW RG210 DB 'ADI',0C6H DW IMMED DB 'ANA',0A0H DW RG210 DB 'ANI',0E6H DW IMMED DB 'CMA',2FH DW DIRCT DB 'CMC',3FH DW DIRCT DB 'CMP',0B8H DW RG210 DB 'CPI',0FEH DW IMMED DB 'DAA',27H DW DIRCT DB 'DCR',05H DW RG543 DB 'DCX',0BH DW RG54B DB 'INR',04H DW RG543 DB 'INX',03H DW RG54B DB 'MOV',40H DW MOVRT DB 'MVI',06H DW MVIRT DB 'NOP',00H DW DIRCT DB 'ORA',0B0H DW RG210 DB 'ORI',0F6H DW IMMED DB 'RAL',17H DW DIRCT DB 'RAR',1FH DW DIRCT DB 'RLC',07H DW DIRCT DB 'RRC',0FH DW DIRCT DB 'SBB',98H DW RG210 DB 'SBI',0DEH DW IMMED DB 'STC',37H DW DIRCT DB 'SUB',90H DW RG210 DB 'SUI',0D6H DW IMMED DB 'XRA',0A8H DW RG210 DB 'XRI',0EEH DW IMMED ; ERTAB: DB ERR AND 0FFH,ITL AND 0FFH,ICM AND 0FFH DB IRR AND 0FFH,IRR AND 0FFH,IIT AND 0FFH DB IIV AND 0FFH,ERR AND 0FFH ; ITL: DB 'INPUT TOO LONG',80H ; ICM: DB 'INVALID COMMAND',80H ; IRR: DB 'INVALID REGISTER',80H ; IIT: DB 'INVALID IMMED TYPE',80H ; IIV: DB 'INVALID IMMED VALUE',80H ; ERR: DB 'ERROR!',80H ; ERRSP: DB CR,LF,90H,80H ; TITLS: DB CLR,CR,LF DB 9BH,'EDUCATOR-8080',CR,LF DB CR,LF,9AH,'<---' DB 'BINARY-----' DB ' OCT HX',CR,LF DB 9AH,'7 6 5 4 3 2 1 0',80H ; BLINE: DB CR,LF,CR,LF,90H DB 'B-REG >> ',80H ; CLINE: DB CR,LF,CR,LF,90H DB 'C-REG >> ',80H ; AFHDR: DB CR,LF,CR,LF,90H DB 'FLAGS & ACC',CR,LF,90H DB 'P Z S A C',CR,LF,90H,80H ; CMDMS: DB CR,LF,CR,LF,90H DB 'COMMAND ? ',80H ; ;CHARACTER OUTPUT ROUTINE ; CHRPR PUSH PSW PUSH B PUSH D PUSH H MOV C,A ;CHARACTER TO C FOR CP/M VCONOUT CALL $-$ ;MODIFIED AT INIT POP H POP D POP B POP PSW RET ; ;KEYBOARD INPUT ROUTINE ; KEYBD PUSH B PUSH D PUSH H VCONIN CALL $-$ ;MODIFIED AT INIT POP H POP D POP B CPI 'C'-40H ;CONTROL-C FOR EXIT? JZ 0 ;YES, REBOOT CP/M RET ; ; DEFINE TEMPORARY STORAGE AREA ; BANDC: ;B AND C REGISTERS CREG: DB 0 BREG: DB 0 PSWA: DW 0 CMDAR: DS 40 STACK EQU $+60 ; END