home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
GENASM
/
EDUCATOR.AQM
/
EDUCATOR.ASM
Wrap
Assembly Source File
|
2000-06-30
|
17KB
|
612 lines
;
; 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