home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
simtel
/
sigm
/
vols000
/
vol075
/
upg80.asm
< prev
next >
Wrap
Assembly Source File
|
1984-04-29
|
58KB
|
2,804 lines
; TITLE 'UPG80 MONITOR SPECIAL SYSTEM VERSION 3-1 31/8/79'
;
;**** FOR S100 SYSTEMS WITH JADE I/O BOARDS.
;
;
;*************************************************************
;
; UPG80 MONITOR :-
; MODIFIED VERSION OF AMSAT'S AMS80 V2:0 MONITOR
; BY H.J.HARVEY
;
; THIS MONITOR IS A MINIMUM 8080 SYSTEM MONITOR TO PROVIDE
; THE BASIC STRUCTURE NECESSARY FOR 8080 DEBUG AND CONTROL.
;
; THE ROUTINES ALLOW FOR MEMORY EXAMINE AND MODIFY,
; TARGET PROGRAM BREAKPOINTING UNDER MONITOR CONTROL,
; USER INTERRUPTS OR RST VECTORS (RST3-RST7),
; SIMPLE ASSEMBLY AND DISASSEMBLY, INPUT AND OUTPUT,
; AND PROVIDE VARIOUS TELETYPE SUPPORT ROUTINES TO LOAD
; AND DUMP MEMORY IN STANDARD 8080 HEX-BINARY.
;
; THE MONITOR INCLUDES AN EXTENSIVE VECTOR TABLE STARTING
; AT (ROM-ORIGIN + 40H) TO ALLOW USER ACCESS TO A NUMBER
; OF USEFUL SPECIFIC ROUTINES.
;
;*************************************************************
;
; DEFINE CONSOLE CONTROL CHRS
;
CR EQU 0DH ;ASCII CARRIAGE-RETURN
LF EQU 0AH ;ASCII LINE-FEED
;
; THE FOLLOWING EQUATES ARE USED TO DEFINE THE COLUMN WIDTH
; OF THE DISPLAY CONSOLE.
; 'R' COMMAND NEEDS 58 COLUMNS FOR A 1-LINE DISPLAY
; 'D' COMMAND NEEDS 53 COLUMNS FOR 16-BYTE DISPLAY
; 'P' COMMAND NEEDS 43 COLUMNS FOR 16-BYTE GROUP
; COLSW=1 IF MONITOR <58 COLUMNS/LINE
; COLSW=0 IF MONITOR >57 COLUMNS/LINE
;
COLSW EQU 0
;
IF NOT COLSW
;
; 58+ COLUMN CONSTANTS
;
OSET EQU 16 ;16 BYTES PER LINE
ENDIF
IF COLSW
;
; <58 COLUMN CONSTANTS
;
OSET EQU 8 ;8 BYTES PER LINE
ENDIF
;
;
;
; THE FOLLOWING EQUATES ARE DESIGNED FOR CONSOLE CONTROL
; OF THE S100 CARD-SET WITH JADE SPI/O BOARDS.
; ER SYSTEMS WILL REQUIRE DIFFERENT EQUATES, DEPENDING
; UPON THE SELECTION OF I/O PORTS AND CONTROL SETUPS.
;
CNCTL EQU 081H ;SYSTEM I/O CONSTANTS
CONST EQU 081H
CNIN EQU 001H
CNOUT EQU 001H
CSCTL EQU 080H ;CASSETTE CONTROL
CSST EQU 080H ;CASSETTE STATUS CHANNEL
CSIN EQU 000H ;CASSETTE INPUT PORT
CSOUT EQU 000H ;CASSETTE OUTPUT PORT
MODE EQU 0FFH ;MM5303 UART MODE SELECT
TRDY EQU 080H ;TRANSMIT READY BIT
RBR EQU 010H ;READER READY BIT
TMOUT EQU 10000 ;10000 MILLISECOND (10 SECS) TIMEOUT
ONEMS EQU 130 ;CONSTANT FOR 1 MILLISECOND LOOP (F/N DELAY)
RAM EQU 03F00H ;START OF 256 BYTE RAM.
;
; ROM AND RAM AREAS CAN NOW BE DEFINED.
;
ROMSW EQU 1 ;ROMSW=1 IF ROM > 0 , OTHERWISE ROMSW=0
ROM EQU 08000H ;ROM STARTS HERE
REGS EQU RAM+256-48 ;REGISTER STORE (IN RAM) STARTS HERE
STACK EQU REGS ;TOP OF STACK INITIALIZE
;
; START OF SYSTEM
;
ORG ROM
;
; SET UP SERIAL DATA MODE.
;
PART1:
DI ;DISABLE ALL INTERRUPTS.
MVI A,MODE ;SERIAL I/O MODE.
JMP PART2
DW RAM
;
; EXECUTIVE ENTRY ON RST1
; THIS ENTRY POINT IS USED WHENEVER AN RST1 (CODE CF)
; IS EXECUTED.
;
EXEC:
SHLD SVHL ;SAVE HL
POP H ;POP THE CALL ADDRESS INTO HL
RAR ;PUT CARRY INTO B7 OF ACC
JMP BEGIN ;GO ON NOW.
;
; BREAKPOINT SERVICING INPUT AS RESULT OF 'RST 2'
; ROUTINE BPAT IS CALLED TO LET THE USER KNOW.
;
BPIN:
SHLD SVHL ;SAVE HL
POP H ;GRAB BREAKPOINT ADDRESS
RAR ;ROTATE RIGHT PUTS CARRY INTO ACC B7
JMP BPAT ;GO SERVICE IT.
;
; DEFINE USER INT/SR VECTORS
; RST3 THROUGH RST7 MAY BE USED EITHER AS HARDWARE
; OR SOFTWARE INTERRUPT VECTORS.
; THE ORRESPONDING ADDRESS FOR SERVICE MUST BE
; SET UP IN THE APPROPRIATE LOCATIONS IN RAM.
; THESE ADDRESSES CAN BE FOUND BY REFERENCE TO THE LABELS
; RST3 - RST7 AT THE END OF THIS MONITOR.
;
;**** NOTE THAT THESE CODE GROUPS ARE TO BE LINKED FROM RAM
; IN PAGE ZERO IF THE MONITOR IS NOT ZERO ORGED.
;
RS3:
PUSH H ;SAVE HL
LHLD RST3 ;FETCH USER VECTOR
XTHL ;PUT ON STACK RESTORING HL
RET ;GO TO USER
DW ROM ;PAD - ROM START ADDRESS
RS4:
PUSH H ;SAVE HL
LHLD RST4 ;FETCH USER VECTOR
XTHL ;PUT ON STACK RESTORING HL
RET ;GO TO USER
DW RAM ;PAD - RAM START ADDRESS
RS5:
PUSH H ;SAVE HL
LHLD RST5 ;FETCH USER VECTOR
XTHL ;PUT ON STACK RESTORING HL
RET ;GO TO USER
DW REGS ;PAD - END OF REG STORE (ALSO T.O.S.)
RS6:
PUSH H ;SAVE HL
LHLD RST6 ;FETCH USER VECTOR
XTHL ;PUT ON STACK RESTORING HL
RET ;GO TO USER
DW SVA ;PAD - START OF REG STORE.
RS7:
PUSH H ;SAVE HL
LHLD RST7 ;FETCH USER VECTOR
XTHL ;PUT ON STACK RESTORING HL
RET ;GO TO USER
DW ENDROM ;PAD - END OF ROM DATA
;
; MONITOR SUPPORT SR VECTORS
; USER UTILITY SR'S
;
; THE FOLLOWING SET OF JUMPS ARE PROVIDED SOTHAT USER
; PROGRAMS CAN REFERENCE COMMON ENTRY POINTS TO THE VARIOUS
; ROUTINES. THESE LOCATIONS WILL REMAIN CONSTANT WHILE THE
; ACTUAL LOCATION OF EACH ROUTINE MAY CHANGE AS DIFFERENT
; MONITOR REVISIONS OCCUR.
;
; THE CALLING SEQUENCE FOR EACH SUBROUTIN EMAINS THE
; SAME AS DEFINED IN THE LISTING, WITH ONLY A SLIGHT EXECUTION
; TIME OVERHEAD DUE TO THE EXTRA JUMP.
;
ZTYPE: JMP TYPE ;TYPE CHR IN 'A'
ZGETCH: JMP GETCH ;GET CHR IN 'A' (PARITY, NO ECHO)
ZCHIN: JMP CHIN ; " " " " (ECHO, NO PARITY)
ZCHINX: JMP CHINX ; " " " " (ECHO/NO ECHO, NO PARITY)
ZMSG: JMP MSG ;TYPE MESSAGE, PTR IN HL. TERM 0FFH
ZCRLF: JMP CRLF ;TYPE CR/LF
ZSPACE: JMP BLANK ;TYPE " "
ZTHXN: JMP THXN ;TYPE HEX 'A' B3-B0
ZTHXB: JMP THXB ; " " " " B7-B0
ZTHXW: JMP THXW ; " " " 'HL'
ZGHXN: JMP GHXN ;GET HEX 'A' B3-B0
ZGHXB: JMP GHXB ; " " " B7-B0
ZGHXW: JMP GHXW ; " " 'HL'
ZSTORE: JMP STORE ;STORE A IN (HL) AND CHECK
ZNEGDE: JMP NEGDE ;NEGATE DE REG
ZPWAIT: JMP PWAIT ;TYPE 'PAUSE' THEN AWAIT ANY CHR
ZOKQ: JMP OKQ ;TYPE 'OK?', AWAIT CHR, CONTINUE IF ' '
ZECHO: JMP ECHCN ;ECHO CONTROL (A=0 MEANS OFF)
ZCNVBN: JMP CNVBN ;CONVERT CHARACTER TO BINARY NYBBLE.
ZCSTS: JMP CSTS ;LOOK FOR CONSOLE K/B STRIKE.
;
; UART INITIALIZATION CODE: PART 2.
; SEND OUT THE COMMAND WORD.
;
PART2:
OUT CSCTL ;SET UP CASSETTE I/O
OUT CNCTL ;AND CONSOLE I/O.
;
; ZERO OUT THE CURRENT ADDRESS FOR BREAKPOINT.
; (NECESSARY TO ALLOW UPDATING)
;
LXI H,0 ;LOAD 16 BIT ZERO
SHLD BPADD ;PUT ALL ZEROS IN BPADD
;
; BEGIN MONITOR.
; ENTER HERE FOLLOWING A HARDWARE/SOFTWARE RST1
;
BEGIN:
SHLD SVPC ;STORE CALLING PC
STA TMPA ;AND CARRY (IN B7)
RAL ;THEN ROTATE BACK THE ACC.
LXI H,0 ;NOW TRANSFER THE SP TO HL BY DOING A DUMMY
DAD SP ;ADD TO HL. (N.B. CLEARS CARRY)
SHLD SVSP ;SAVE THE CALLER SP.
LXI SP,SVA+1 ;PICK UP REG STORE POINTER
PUSH PSW ;TO SAVE PSW
PUSH B ;AND BC
PUSH D ;AND DE. (HL ALREADY SAVED)
LXI H,SVF ;GET THE PSB BYTE
LDA TMPA ;PICK UP THE CARRY HOLDER,
RAL ;ROTATE IT BACK TO CARRY.
JNC BGN1 ;SKIP IF CARRY NOT SET,
INR M ;OTHERWISE RESET CARRY.
BGN1:
LXI H,M0 ;TYPE MONITOR ENTRY MESSAGE
JMP NEXT1
;
; NEXT MONITOR COMMAND PLEASE.
; ENTER HERE WHENEVER A NEW COMMAND IS EXPECTED.
;
NEXT:
LXI H,M1 ;TYPE PROMPT MESSAGE
NEXT1:
LXI SP,STACK ;SET STACK POINTER FIRST.
CALL MSG
CALL CHIN ;GET COMMAND CHARACTER INTO 'A'
MOV B,A ;AND SAVE IT IN 'B'
;
; SEARCH OP TABLE
; (IF CALLING COMMAND BYTE IS REQUIRED, IT IS IN 'B')
;
LXI H,OPTAB ;HEAD-OF-TABLE VECTOR
SUI 'A' ;REDUCE CODE TO OFFSET
CPI 1AH ;SEE IF IT EXCEEDS 'Z' COMMAND.
JNC TEND ;IF SO, MAY HAVE BEEN SPECIAL.
ADD A ;ALL O.K. MULTIPLY BY 2 (2 BYTES PER ADDR)
MOV E,A ;PUT VALUE*2 INTO E
MVI D,0 ;AND GET ZERO TO CLEAR 'D'
DAD D ;ADD OFFSET TO HL (ADDRESS REQUIRED AT <HL>)
MOV E,M ;GET LOWER BYTE OF REQUIRED ADDR
INX H ;AND THEN GET THE UPPER
MOV D,M ;BYTE BEFORE TRANSFERRING
XCHG ;IT TO HL.
PCHL ;FINALLY JUMP TO ROUTINE CALLED.
;
; OPERATION ADDRESS TABLE.
; CONTAINS AN ADDRESS DESTINATION FOR EACH CHARACTER OF THE
; ALPHABET (A-Z IN ASCENDING ORDER.)
;
OPTAB:
DW GETAD ;A - GET ADDRESS
DW BPT ;B - BREAKPOINT SETTER/CLEARER
DW CONT ;C - CONTINUE AFTER B/P
DW DISP ;D - DISPLAY MEMORY DATA
DW PEND ;E - END OF FILE PUNCH
DW FILL ;F - FILL MEMORY WITH DATA
DW GOTO ;G - PROGRAM GO: NO REGISTER RESTORE.
DW ASM80 ;H - LINE ASSEMBLER
DW INPT ;I - INPUT PORT DATA
DW JUMP ;J - PROGRAM JUMP: REGISTER RESTORE.
DW KOMP ;K - K(C)OMPARE MEMORY AREAS
DW LOAD ;L - LOAD HEX-BINARY TAPE
DW MOVE ;M - MOVE MEMORY BLOCK
DW NULL ;N - PUNCH NULL BLOCK
DW OUTPT ;O - OUTPUT PORT DATA.
DW PUNCH ;P - PUNCH HEX-BINARY DATA
DW ILLEG
DW REGEX ;R - REGISTER EXAMINE/MODIFY
DW SEARCH ;S - SEARCH MEMORY FOR BYTE
DW ILLEG
DW USER ;U - USER DEFINE/USE
DW ILLEG
DW ILLEG
DW GETXA ;X - SET UP XEQ ADDRESS
DW DIS80 ;Y - 8080 DISASSEMBLY.
DW ZERO ;Z - ZERO OUT MEMORY
;
; N.B. COMMANDS <CR> <LF> . AND - ARE CHECKED
; BY ROUTINE 'TEND'
;
;
; INPUT ONE CHR AND STRIP PARITY
; ALTERNATIVE ENTRY POINTS ARE:-
;
; CALL CHIN
; .... ;RESULT IN 'A'
; THE INPUT IS ECHO'D IF DATA IS PRINTABLE.
;
; MVI A,XX ;XX=0 NO ECHO.
; CALL CHINX
; .... ;RESULT IN 'A'
; ECHO CONTROLLED EACH CALL.
;
; CALL CHINN
; .... ;RESULT IN 'A'
; ECHO CONTROLLED BY PREVIOUS 'CALL ECHCN'
;
CHIN:
MVI A,0FFH ;SET ECHO FLAG ON
CHINX:
CALL ECHCN ;CALL THE CONTROLLER.
CHINN:
CALL GETCH ;GET CHARACTER FROM CONSOLE,
ANI 7FH ;STRIP ANY PARITY
PUSH PSW ;SAVE DATA
LDA ECHO ;SEE IF ECHO REQU'D
ANA A ;THIS INSTRUCTION SIMPLY SETS FLAGS
JNZ CHN1 ;TEST FOR ZERO/NON-ZERO CONTROL
POP PSW ;NO ECHO. SIMPLY RETURN
RET
CHN1:
POP PSW ;GET DATA AND ECHO
CPI ' ' ;IF NOT CONTROL CHR
CNC TYPE
RET ;BEFORE RETURNING
;
; MESSAGE PRINT
; ALLOWS USER TO PRINT A MESSAGE ON THE CONSOLE OUTPUT
; BY HAVING A STRING OF CHARACTERS FOLLOWED
; BY DELIMITING 0FFH (-1)
;
; CALLING SEQUENCE:-
; LXI H,ADDRESS
; CALL MSG
; ....
;
MSG:
PUSH PSW ;SAVE PSW
PUSH H ;AND HL
MNXT:
MOV A,M ;GET NEXT BYTE
INX H ;BUMP BYTE POINTER.
CPI 0FFH ;CHECK FOR 0FFH (-1) TERMINATOR
CNZ TYPE ;NO. TYPE IT
JNZ MNXT ;NOW READY FOR ANOTHER TRY
POP H ;MESSAGE FINISHED. RESTORE HL
POP PSW ;AND PSW
RET ;BEFORE GOING HOME
;
; TYPE CR/LF
; (THE EASY WAY TO START A NEW LINE)
;
; CALLING SEQUENCE:-
; CALL CRLF
; ....
;
CRLF:
PUSH H ;SAVE HL
LXI H,M2 ;GET CR/LF MESSAGE
CALL MSG ;TYPE MESSAGE
POP H ;RESTORE HL
RET ;RETURN
;
;
; TYPE ONE SPACE
;
; CALLING SEQUENCE:-
; CALL BLANK
; ....
;
BLANK:
PUSH PSW ;SAVE PSW
MVI A,' ' ;GET SPACE
CALL TYPE ;TYPE IT
POP PSW ;RESTORE PSW
RET ;THEN RETURN
;
; TYPE 'A' IN HEX
; OUTPUTS THE 2-BIT HEX VALUE OF ACCUMULATOR
; TO CONSOLE
;
; CALLING SEQUENCE:-
; LDA DATA
; CALL THXB
; ....
;
THXB:
PUSH PSW ;SAVE PSW
RRC ;SHIFT THE LEFT NYBBLE
RRC ;INTO THE RIGHT NYBBLE
RRC ;BY DOING 4 ROTATE RIGHTS.
RRC
CALL THXN ;TYPE HEX NYBBLE
POP PSW ;RESTORE DATA
;
; TYPE 'A' B3-B0 IN ASCII
; TYPES THE 1-BIT HEX VALUE OF THE BOTTOM 4 BITS
; OF ACCUMULATOR.
;
; CALLING SEQUENCE:-
; LDA DATA
; CALL THXN
; ....
;
THXN:
PUSH PSW ;SAVE PSW
ANI 0FH ;ISOLATE B3-B0 (THROW AWAY B7-B4)
ADI 090H ;ADJUST
DAA ;NOW
ACI 040H ;TO
DAA ;ASCII
CALL TYPE ;BEFORE TYPING
POP PSW ;RESTORE PSW
RET ;THEN RETURN
;
;
; TYPE A WORD IN HEX
; TYPES THE 4-BIT HEX VALUE OF THE 16-BIT VALUE
; HELD IN THE HL REGISTER PAIR.
;
; CALLING SEQUENCE:-
; LHLD WORD
; CALL THXW
; ....
;
THXW:
PUSH PSW ;SAVE PSW
MOV A,H ;GET HIGH BYTE FROM 'H'
CALL THXB ;AND TYPE IT
MOV A,L ;GET LOW BYTE FROM 'L' AND
CALL THXB ;TYPE IT TOO.
POP PSW ;RESTORE PSW
RET ;I'M GOIN HOME
;
; GET HEX CHR FROM CONSOLE
; ROUTINE TO GET A SINGLE HEX NYBBLE FROM THE CONSOLE
; IF THE DIGIT IS VALID (I.E. 0-9,A-F) THEN THE BINARY
; VALUE IS RETURNED IN 'A' AND THE CARRY IS RESET.
;
; HOWEVER, IF THE RESULT IS NON-HEX, THE BAD CHARACTER
; WILL BE IN 'A' AND CARRY WILL BE SET.
;
; CALLING SEQUENCE:-
; CALL GHXN
; JC NONHX ;ERROR IF CARRY SET
;
GHXN:
MVI A,0FH ;MASK TO KEEP ONLY THE RIGHT NYBBLE
JMP GHB1
;
; GET HEX BYTE FROM CONSOLE
; SIMILAR TO GHXN, BUT RETURNS BYTE VALUE IF O.K.
;
; CALLING SEQUENCE:-
; CALL GHXB
; JC NONHX ;CHECK NO HEX I/P
;
GHXB:
MVI A,0FFH ;MASK TO KEEP WHOLE BYTE.
GHB1:
PUSH H ;SAVE HL
CALL GHXW ;GET HEX DATA VIA GHXW
JC GHB2 ;PROVIDED THERE HAS BEEN NO ERROR,
ANA L ;WE CAN MASK THE NYBBLE/BYTE.
GHB2:
POP H ;RESTORE HL
RET ;RETURN TO CALLER
;
; GET HEX WORD FROM CONSOLE
; SIMILAR TO GHXN, BUT RETURNS BINARY WORD (16-BIT)
; IN HL REG PAIR IF O.K.
;
; CALLING SEQUENCE:-
; CALL GHXW
; JC NONHX ;TEST NON HEX I/P
; .... ;RESULT IN HL
;
GHXW:
PUSH PSW ;SAVE PSW
LXI H,0 ;ZERO OUT THE HL STORE
CALL CHINN ;GET FIRST CHARACTER, CONTROLLED ECHO
CALL CNVBN ;CONVERT IT TO BINARY NYBBLE
JC GHW3 ;ANY NON-HEX IS ERROR FIRST TIME.
MOV L,A ;SAVE FIRST DIGIT
GHW1:
CALL CHINN ;GET ANOTHER CHARACTER
CALL CNVBN ;AND CONVERT TO BINARY NYBBLE
JC GHW2 ;AFTER FIRST DIGIT, CHECK FOR DELIMITER.
DAD H ;HL*2 ;WE WANT 1-NYBBLE LEFT SHIFT
DAD H ;HL*4 ;SO WE DOUBLE ADD HL
DAD H ;HL*8 ;TO ITSELF FOUR TIMES.
DAD H ;HL*16 ;N.B. TOP DIGIT IS LOST.
ADD L ;ALL DONE. ADD DIGIT TO LOWER BYTE
MOV L,A ;UPDATE THE LOWER BYTE.
JMP GHW1 ;NEXT DIGIT PLEASE.
GHW2:
CPI CR ;COMPARE WITH CR
JZ GHW4
CPI ' ' ;AND SPACE
JZ GHW4 ;EITHER IS VALID DELIMITER.
GHW3:
INX SP ;NON-HEX BAD BYTE IS RETURNED
INX SP ;IN A, WITH CARRY SET.
STC
RET
GHW4:
POP PSW ;NORMAL EXIT, RESTORE PSW
ORA A ;WITH CARRY CLEARED.
RET
;
; CNVBN: CONVERT ASCII TO BINARY NYBBLE,
; IS COMMON TO GHXN,GHXB,GHXW
;
CNVBN:
CPI '0' ;FIRST SEE IF <'0'
RC
CPI '9'+1 ;NOW SEE IF NUMERIC
JC CNVB1 ;IT IS IF CARRY ON.
CPI 'A' ;NOW TRY A-F
RC ;ERROR RETURN IF CARRY SET
CPI 'F'+1 ;CHECK FOR >F
CMC ;INVERT CARRY
RC ;RETURN IF NOT OK.
SUI 7 ;A-F CHR FOUND. SUBTRACT 7
CNVB1:
SUI '0' ;NOW MAKE INTO BINARY
RET ;THEN RETURN
;
; STORE BYTE IN MEMORY, WITH READ CHECK.
; IF READ-BACK DOES NOT AGREE WITH STORE REQUEST AN
; APPROPRIATE ERROR MESSAGE IS ISSUED.
;
; CALLING SEQUENCE:-
; ;DATA IN 'A', ADR IN 'HL'
; CALL STORE
; .... ;RETURNS HERE IF O.K.
; ;OTHERWISE RETURNS TO MONITOR.
;
STORE:
MOV M,A ;STORE BYTE INTO MEMORY
CMP M ;COMPARE MEMORY WITH A
RZ ;RETURN IF O.K.
PUSH H ;SUMTHIN IS WRONG.
LXI H,M4 ;ISSUE ERROR MESSAGE
CALL MSG ;TO ADVISE USER
POP H ;RESTORE HL
JMP RXAR ;INDICATE ERROR LOC'N
;
;
; MEMORY EXAMINE/MODIFY.
;
; ENTER FROM MONITOR BY USING:-
; A 1234
; SETS 'ADR' TO '1234H', TYPES CURRENT CONTENTS THEN AWAITS :-
;
; (1) VALID BYTE TO STORE, THEN BUMPS 'ADR'
; (2) LF TO SIMPLY BUMP 'ADR'
; (3) - TO SIMPLY DECREMENT 'ADR'
; (4) CR TO RETURN TO MONITOR
; (5) . TO RETYPE CURRENT ADR
;
; IN ADDITION, AT ANY TIME THE USER MAY DIRECTLY
; ENTER THIS ROUTINE WITH:-
; (1) . TO TYPE CONTENTS OF CURRENT 'ADR'
; (2) - TO TYPE CONTENTS OF PREVIOUS 'ADR'
; (3) LF TO TYPE CONTENTS OF NEXT 'ADR'
; ROUTINE THEN CONTINUES AS ABOVE.
;
GETAD:
CALL PUWA ;GET ADR REQUIRED
XCHG
;
GTA1:
SHLD ADR ;SAVE ADR
LOCAT:
CALL CRLF ;CR/LF
LHLD ADR ;FETCH CURRENT ADR
CALL THXW ;TYPE CURRENT ADR
CALL BLANK ;FOLLOWED BY SPACE
MOV A,M ;FOLLOWED BY BYTE CONTENT
CALL THXB
CALL BLANK ;YET ANOTHER SPACE
CALL GHXB ;LOOK FOR NEW BYTE
JC NONHX ;CHECK NON-HEX I/P
CALL STORE ;TRY TO STORE DATA BYTE
NXLOC:
LHLD ADR ;PICK UP CURRENT ADR
INX H ;BUMP 1
JMP GTA1 ;RESTART PROCESS OF ADR ACCESS.
;
; ROUTINE 'TEND' IS CALLED FROM MONITOR OP-TAB
; TABLE END ROUTINE
;
TEND:
MOV A,B ;SET 'A' TO COMMAND
NONHX:
CPI LF ;SEE IF CHARACTER WAS LF
JZ NXLOC ;IF SO, GET NEXT LOC'N
CPI '.' ;MAYBE IT WAS '.'
JZ LOCAT ;IF SO, GET SAME LOC'N
CPI '-' ;OR EVEN '-'
JZ LSTLC ;IN WHICH CASE, BACK UP 1 LOC'N
NONH1:
CPI CR ;FINAL CHANCE IS CR
JZ NEXT ;WHICH MEANS EXIT THE COMMAND
;
; IN THE EVENT THAT THE COMMAND IS NO GOOD,
; ENTER HERE.
;
ILLEG:
LXI H,M3 ;ILLEGAL CALL, SEND QUERY MESSAGE.
ILLG1:
CALL MSG ;TYPE IT, THEN
JMP NEXT ;'AVE ANOTHER GO.
;
; PREVIOUS LOCATION REQUEST.
;
LSTLC:
LHLD ADR ;BACKUP 1 BYTE
DCX H
JMP GTA1 ;AND TRY AGAIN.
;
; NEGATE (2'S COMPLEMENT) 'DE' REG PAIR
;
; CALLING SEQUENCE:-
; .... ;SET UP DE
; CALL NEGDE
; .... ;NOW DE=-DE
;
NEGDE:
PUSH PSW ;SAVE PSW
MOV A,D ;FETCH D
CMA ;COMPLEMENT IT
MOV D,A ;RESTORE
MOV A,E ;FETCH E
CMA ;COMPLEMENT IT TOO
MOV E,A ;THE RESTORE
INX D ;NOW ADD 1 TO GET 2'S COMPL
POP PSW ;RESTORE PSW
RET ;TAKE RESULTS HOME
;
; DISPLAY BLOCK OF MEMORY ON CONSOLE.
; CALLED FROM MONITOR AS:-
; D XXXX YYYY
; AFTER THE FIRST LINE, PRINTS XXXX TO YYYY IN
; 8/16 BYTE GROUPS STARTING WITH ADR,MOD 8/16
; IF XXXX > YYYY ONLY PRINTS CONTENTS OF XXXX
;
DISP:
CALL PICKUP ;GET ADDRESS RANGE.
DMRET:
CALL CRLF ;NEW LINE
CALL THXW ;VECTOR ADR TO CONSOLE
DMNXT:
CALL BLANK ;1 SPACE
MOV A,M ;GET DATA
CALL THXB ;TYPE IT
CALL LAST ;ALL DONE?
CALL HOLD ;NO. SEE IF HOLD REQUEST.
MOV A,L ;ADR MOD8/16?
ANI OSET-1
JNZ DMNXT ;NO.
JMP DMRET ;YES. NEW LINE.
;
; LOCAL ROUTINE TO TEST FOR HOLD REQUEST.
; RETURNS IF NO CHARACTER IN INPUT BUFFER.
; PUTS HOLD ON OUTPUT IF <SP> IS TYPED.
; OTHERWISE RETURNS TO MONITOR.
;
HOLD:
CALL CSTS ;GET CONSOLE STATUS.
RZ ;ZERO. RETURN.
XRA A ;NON-ZERO.
CALL CHINX ;GET CHARACTER, NO ECHO.
CPI ' ' ;TEST FOR SPACE
JNZ NEXT ;NO SPACE. PANIC.
JMP GETCH ;SPACE. AWAIT CONTINUE.
;
; LOCAL ROUTINE TO PICK UP TWO ADDRESSES,
; PUTTING THE FIRST ADDRESS INTO HL
; AND THE NEGATED SECOND ADDRESS INTO DE
;
PICKUP:
CALL PUWA ;FROM ADDRESS INTO DE
CALL PUWA ;FROM ADDRESS INTO HL,
JMP NEGDE ;NEGATED TO ADDRESS IN DE
;
; JUMP TO ADDRESS WITH REG'S SET
;
; CALLED FROM MONITOR BY:-
; J 1234 JUMP TO SPECIFIED HEX ADR
; J <CR> JUMP TO ADR FROM LAST RST1
; (USED AS BREAKPOINT IN PROGRAMS)
; J <LF> JUMP TO ADR SET UP BY 'X' COMMAND
; J . JUMP TO ADR SET BY LAST USE OF 'A' COMMAND
;
; RESTORES REGISTERS TO STATE AS SAVED IN RAM ON ENTRY
; TO THE MONITOR.
; RESPONSES J <CR> , J <LF> AND J . WILL TYPE
; THE STORED ADDRESS BEFORE ASKING FOR OK TO PROCEED.
;
; REMEMBER IF RST1 WAS USED, THAT THE RETURN ADDRESS MAY
; NEED TO BE RESET WITH THE 'RP=' COMMAND TO GET YOU
; BACK TO THE CALLING POINT.
;
;
; GO DIRECT TO ADR FROM MONITOR.
; IDENTICAL TO 'J' COMMAND, BUT DOES
; NOT RESTORE REGISTERS.
;
JUMP:
GOTO:
PUSH B ;SAVE INPUT COMMAND
CALL PUWB ;GET ADR
JNC JMP4 ;HEX ADR GIVEN
JMP2:
LHLD SVPC ;ASSUME SAVED PC REQUIRED.
CPI CR ;SEE IF CR
JZ JMP3
LHLD XEQAD ;NO. ASSUME 'X' ADDRESS REQUEST.
CPI LF ;TRY LF
JZ JMP3 ;IF NOT,
LHLD ADR ;ONLY ALTERNATIVE IS 'ADR'
CPI '.' ;MUST BE '.'
JNZ ILLEG ;NO. PANIC.
JMP3:
CALL THXW ;TYPE HEX ADR
JMP4:
CALL OKQ ;IS THIS WHERE WE REALLY WANT TO GO?
SHLD GOGO+1 ;YES. SET UP JUMP ADR
MVI A,0C3H ;THIS IS 'JMP' COMMAND
STA GOGO ;WHICH WE SET UP IN RAM
POP PSW ;RECOVER COMMAND CHARACTER.
CPI 'G' ;WAS IT 'G' ?
JZ GOGO ;YES. IMMEDIATE JUMP TO PROGRAM.
LXI SP,SVE ;NO. RESTORE SP
POP D ;AND REGS
POP B
POP PSW
LHLD SVSP ;SAVED SP
SPHL ;SET NEW SP
LHLD SVHL ;AND HL
JMP GOGO ;CUNNINGLY EXECUTE BUILT-UP JUMP
;
; SET UP EXECUTION ADR FROM MONITOR BY:-
; X 1234
;
GETXA:
CALL PUWA ;GET ADR
XCHG ;INTO HL
SHLD XEQAD ;PUT INTO XEQAD
JMP NEXT ;BACK TO MONITOR
;
; LOCAL ROUTINE TO CHECK FOR LAST OPERATION.
;
LAST:
PUSH H ;SAVE MEM VECTOR
DAD D ;ADD NEGATIVE ADDRESS
JC NEXT ;FINITO IF CARRY SET
POP H ;NO. RESTORE
INX H ;BUMP ADR
RET ;RETURN
;
; COMPARE TWO MEMORY BLOCKS, PRINT ANY DIFFERENCES.
; USES 'MOVE' TO ALLOCATE THE BLOCK ADDRESSES.
;
; MOVE MEMORY BLOCK FROM MONITOR BY:-
; M XXXX YYYY ZZZZ
;
; MOVES BLOCK XXXX TO YYYY INTO ZZZZ ONWARDS
; TAKE CARE. WILL RESULT IN OVERWRITES IF ZZZZ IS
; IN THE RANGE XXXX+1 TO YYYY
; CAN BE USED AS A 'FILL' OPERATION BY PUTTING
; ZZZZ=XXXX+1. LAST FILL OCCURS AT YYYY+1.
;
KOMP:
MOVE:
CALL PUWA ;GET XXXX
PUSH D ;SAVE ON STACK
CALL PUWA ;GET YYYY IN DE
CALL PUWA ;GET ZZZZ IN DE, YYYY GOES TO HL
XCHG ;DE=Y HL=Z STACK=X
XTHL ;DE=Y STACK=Z HL=X
CALL NEGDE ;NEGATE DE
MOV A,B ;GET COMMAND AND SEE
CPI 'M' ;IF IT WAS 'M'
JNZ KOMP1 ;JUMP IF IT WAS NOT.
CALL OKQ ;MOVE. ARE YOU SURE, USER?
MOV1:
MOV A,M ;GET THRU X
XTHL ;HL=Z STACK=X
CALL STORE ;STORE AND CHECK
INX H ;BUMP Z
XTHL ;RESTORE
CALL LAST ;END YET?
JMP MOV1 ;NO.
;
; REGISTER MODIFY/EXAMINE. FROM MONITOR BY:-
;
; R <CR> TYPE ALL REG CONTENTS
; RA ACCUMULATOR
; RF FLAGS,PSB
; RB REG B
; RC REG C
; RD REG D
; RE REG E
; RH REG H
; RL REG L
; RS STACK POINTER ***
; RP PC IF MONITOR 'CALLED' ***
;
; *** NOTE: RS, RP GIVE AND EXPECT 4-HEX DIGITS
;
RXLST: DB 'AFBCDEHL',0 ;REGISTER LIST
;
REGEX:
CALL CHIN ;GET REGISTER IDENTIFIER
CPI CR ;IS IT CR?
JZ REXAL ;YEP.
PUSH PSW ;NO. SAVE PSW
MVI A,'='
CALL TYPE ;TYPE A '='
POP PSW ;RESTORE IDENT
LXI D,SVPC ;ADR OF P.C.
CPI 'P' ;SEE IF PC REQUEST
JZ RX2 ;YES.
INX D ;POINT TO SP
INX D
CPI 'S' ;IS IT 'S'
JZ RX2 ;YES.
MOV B,A ;NO. SAVE ID IN B
LXI H,RXLST ;LIST VECTOR ADR
LXI D,SVA ;ADR OF 'A' STORE
RX0:
MOV A,M ;GET TABLE ID
ANA A ;CHECK FOR END (0)
JZ ILLEG ;YES. ILLEGAL REQUEST
CMP B ;COMPARE WITH REQUEST
JZ RX1 ;FOUND?
INX H ;NO. NEXT ENTRY
DCX D ;NEXT REG
JMP RX0 ;NEXT TRY.
;
RX1:
LDAX D ;GET REG
CALL THXB ;TYPE IT OUT
CALL BLANK ;FOLLOWED BY SPACE
CALL GHXB ;GET RESPONSE
JC NONH1 ;NON-HEX. TRY CR LATER
STAX D ;STORE INPUT IN REG
JMP NEXT ;BACK HOME, JAMES.
;
RX2:
XCHG ;REG ADR TO HL
MOV E,M ;LOW S OR P
INX H ;BUMP VECTOR
MOV D,M ;HI S OR P
XCHG ;REG VAL IN HL
CALL THXW ;TYPE HEX WORD
CALL PUWB ;GET CHANGE.
JC NONH1 ;NON-HEX JUMP
XCHG ;RESTORE RAM VECTOR
MOV M,D ;STORE HI S OR P
DCX H ;DROP VECTOR
MOV M,E ;STORE LO S OR P
JMP NEXT ;RETURN
RXTSE:
CALL BLANK ;SPACE
CALL TYPE ;TYPE THE ID.
MVI A,'='
JMP TYPE ;EQUALS
;
REXAL:
LXI D,SVA ;ADR OF 'A'
LXI H,RXLST ;ID LIST
RXA1:
MOV A,M ;GET ID
ANA A ;LAST YET? (0)
JZ RXA2 ;YES
;
; THIS LITTLE BIT OF CODE GOES IN ONLY IF WE ARE MAKING
; A 32 COLUMN CONFIGURED DISPLAY MONITOR.
;
IF COLSW
CPI 'E' ;SEE IF NEXT REGISTER IS 'E'
CZ CRLF ;IF SO, NEXT LINE PLEASE,
ENDIF
;
; THE ALTERNATIVE IS A 5-BYTE DUMMY PATCH.
;
IF NOT COLSW
NOP
NOP
NOP
NOP
NOP
ENDIF
;
CALL RXTSE ;TYPE ' ',ID,'='
LDAX D ;GET REG
DCX D ;DROP REG PTR
INX H ;BUMP LIST PTR
CALL THXB ;TYPE CONTENTS
JMP RXA1 ;NEXT PLEASE.
RXA2:
MVI A,'P' ;DO PC
CALL RXTSE
LHLD SVPC ;GET PC
CALL THXW ;TYPE PC
MVI A,'S' ;NOW DO SP
CALL RXTSE
LHLD SVSP ;GET SP
RXAR:
CALL THXW ;TYPE VALUE
JMP NEXT ;RETURN TO MOM.
;
; HEX WORD PICKUPS.
; PUWA GETS WORD, AND RETURNS TO MONITOR IF ERROR.
; IF NOT PUTS RESULT IN 'DE'.
;
PUWA:
CALL PUWB ;GET A HEX WORD
JC ILLEG ;BADDY OUT HERE
XCHG ;SAVE INTO DE
RET ;RETURN
;
; PUWB GETS WORD INTO 'HL' WITHOUT CHECK.
;
PUWB:
CALL BLANK ;TYPE A BLANK FIRST.
JMP GHXW ;NOW GET THE WORD.
;
; PAUSE GENERATOR.
; TYPES THE MESSAGE 'PAUSE' THEN AWAITS ANY KEYSTRIKE
; (NO ECHO) BEFORE CONTINUING.
;
PWAIT:
PUSH H ;SAVE HL
LXI H,M5 ;MESSAGE 'PAUSE'
CALL MSG
POP H ;RECOVER
JMP GETCH ;ANY RESPONSE WILL DO.
;
; MONITOR OR USER VERIFY ROUTINE OK?
; CALLING SEQUENCE:-
; CALL OKQ
; .... ;GOES HERE IF RESPONSE IS SP
; ;OTHERWISE ABORTS.
;
OKQ:
PUSH PSW ;SAVE PSW
PUSH H ;AND HL
LXI H,M7 ;ADR OF 'OK?' MESSAGE
CALL MSG ;PRINT IT
LXI H,M8 ;PREPARE TO ABORT
CALL GETCH ;USER'S REPLY
ANI 7FH ;MASK OUT PARITY.
CPI ' ' ;TRY ' '
JNZ ILLG1 ;NO. ABORT
POP H ;YES. RESTORE HL
POP PSW ;AND PSW
RET ;AND GO ON.
;
; ECHO ON/OFF CONTROLLER.
;
; CALLING SEQUENCE:-
; MVI A,XX ;XX=0 FOR OFF
; ;XX<>0 FOR ON
; CALL ECHCN
; .... ;NOW SET/RESET.
;
ECHCN:
STA ECHO ;STORE REQUIRED VALUE
RET
;
; SYSTEM I/O ROUTINES
;
;******* THIS VERSION SUITS JADE PSI/O SYSTEM HARDWARE *******
;
; USER MUST PUT HIS OWN CONSOLE DRIVER IN HERE
; IF DIFFERENT TO THE VERSION SHOWN
;
;
; TYPE A CHARACTER.
; CALLING SEQUENCE:-
; LDA CHR
; CALL TYPE ;TYPE IT
; ....
;
;
; ROUTINE CO IS A PATCH FOR SBC80/SDK80 SYSTEMS
; WHICH PASS ARGUMENT IN 'C'
;
CO:
MOV A,C ;PUT ARGUMENT INTO A
TYPE:
PUSH PSW ;SAVE CONTENTS OF 'A'
TYP1:
IN CONST ;GET CONSOLE STATUS
ANI TRDY ;ZERO INDICATES BUSY.
JZ TYP1 ;IF SO, TRY AGAIN.
POP PSW ;CLEAR. RESTORE 'A'
OUT CNOUT ;OUTPUT TO 'CNOUT'
RET
;
; RETRIEVE CHARACTER FROM CONSOLE
; PARITY IS KEPT, BUT NO ECHO GIVEN.
; CALLING SEQUENCE:-
; CALL GETCH ;GET CHARACTER
; .... ;CHARACTER IN 'A'
;
;
; NOTE: THIS IS ALSO THE ENTRY POINT FOR SDK80/SBC80
; ROUTINE CI.
;
CI:
GETCH:
CALL CSTS ;GET CONSOLE STATUS
JZ GETCH ;IF SO, TRY AGAIN.
IN CNIN ;READY. GET A CHARACTER.
RET ;RETURN WITH CHAR IN 'A'
;
; CONSOLE STATUS ROUTINE. CALLED BY DISP AND PUNCH
; TO ALLOW STOPPING OF OUTPUT BY TYPING ANY CHAR.
; THE BREAK CHARACTER IS THE FIRST CHARACTER INPUT
; TO THE MONITOR AFTER RETURN.
; (IDEAL BREAK CHARACTER IS <SP>. RESULTS IN MONITOR QUERY)
;
CSTS:
IN CONST ;GET CONSOLE STATUS
ANI RBR ;INPUT BUFFER READY?
RET ;RETURN
;
;
; SYSTEM MESSAGES.
;
M0: DB CR,LF,'UPG80 V3:1'
M1: DB CR,LF,'* ',0FFH
M2: DB CR,LF,0FFH
M3: DB ' ??',0FFH
M4: DB CR,LF,'MEMORY ERR @ ',0FFH
M5: DB ' PAUSE ',0FFH
M7: DB ' OK? ',0FFH
M8: DB 'ABORT',0FFH
ORG ROM+0400H
;
M6: DB ' CKS ERR @ ',0FFH
M10: DB CR,LF,'B/P @ ',0FFH
;
; SEARCH MEMORY FOR A GIVEN BYTE.
; CALLED FROM MONITOR BY:-
; S XXXX YYYY VV
;
; WHERE XXXX= STARTING ADDRESS FOR SEARCH
; YYYY= FINISHING ADDRESS FOR SEARCH
; VV= BYTE TO BE FOUND
;
;
SEARCH:
CALL PICKUP ;GET BLOCK ADDRESSES.
CALL GBYTE ;NOW SPACE AND BYTE REF.
MOV B,A ;SAVE IT IN 'B'
CALL SRC4 ;START A NEW LINE
SRC1:
CALL HOLD ;SEE IF HOLD CALLED.
MOV A,M ;GET COMPARE.
CMP B ;COMPARE BYTE WITH MEMORY
CZ SRC3 ;PRINT ADDRESS IF EQUAL.
SRC2:
CALL LAST ;NOW SEE IF ALL DONE.
JMP SRC1 ;IF NOT, CONTINUE SEARCH
;
; SRC3 PRINTS ADDRESS
; SRC4 SETS UP FOR NEW LINE.
;
SCNT EQU OSET/2
;
SRC3:
CALL BLANK ;ONE SPACE PLEASE,
CALL THXW ;FOLLOWED BY THE ADDRESS.
DCR C ;DECREMENT THE LINE COUNT
RNZ ;RETURN PRONTO IF NOT FULL.
SRC4:
CALL CRLF ;START ON NEW LINE,
MVI C,SCNT ;LOAD SEARCH COUNTER.
RET ;THEN CONTINUE ON OUR MERRY WAY.
;
; COMPARE MEMORY. STARTED OUT IN 'MOVE' FUNCTION WHERE
; IT GOT THE ADDRESSES.
; CALLED FROM THE MONITOR BY:-
; K XXXX YYYY ZZZZ
; WHERE XXXX=START ADDR OF FIRST BLOCK
; YYYY=STOP ADDR OF FIRST BLOCK
; ZZZZ=START ADDR OF SECOND BLOCK
; PRINTS OUT ALL OCCURRENCES OF INEQUALITY.
;
KOMP1:
CALL HOLD ;SEE IF HOLD REQUESTED.
MOV A,M ;GET FIRST BLOCK BYTE.
XTHL ;SWAP HL AND T.O.S.
CMP M ;NOW COMPARE WITH SECOND BYTE
JZ KOMP2 ;SKIP IF ALL THE SAME.
CALL SRC4 ;NEW LINE FIRST
XTHL ;SWAP POINTERS
CALL KOMP3 ;FIRST ADDR/BYTE
XTHL ;SWAP THEM BACK
MOV A,M ;SECOND BYTE IN.
CALL KOMP3 ;PRINT THEM TOO.
KOMP2:
INX H ;BUMP THE SECOND ADDRESS
XTHL ;BACK WHERE WE STARTED.
CALL LAST ;SEE IF ALL DONE.
JMP KOMP1
KOMP3:
CALL SRC3 ;PRINT SPACE AND ADDRESS.
CALL BLANK ;A SPACE
JMP THXB ;THEN BYTE VALUE
;
;
; ZERO OUT A BLOCK OF MEMORY.
; CALLED FROM MONITOR BY:-
; Z XXXX YYYY
; (THE VALUE VV=0 FOR THIS FUNCTION)
;
;
; FILL BLOCK WITH A VALUE. MONITOR CALL BY:-
;
; F XXXX YYYY VV
;
; CAUSES MEMORY LOCATIONS XXXX THRU YYYY TO BE
; SET TO THE VALUE VV.
;
ZERO:
FILL:
CALL PICKUP ;GET BLOCK ADDRESSES.
MOV A,B ;GRAB THE COMMAND BYTE (F OR Z)
CPI 'Z' ;COMPARE WITH 'Z'
MVI A,0 ;ASSUME ZERO REQUESTED, THEN
JZ FILL0 ;JUMP IF TRUE.
CALL GBYTE ;ELSE GET THE FILLING BYTE.
FILL0:
CALL OKQ ;VERIFY FILL/ZERO REQUEST
FILL1:
CALL STORE ;STORE AND CHECK
CALL LAST ;END IN SIGHT?
JMP FILL1 ;NOT YET.
;
;**** GET BYTE WITH TEST.
;
GBYTE:
CALL BLANK ;LEADING BLANK
CALL GHXB ;THEN THE BYTE.
JC ILLEG ;TEST LEGALITY.
RET
;
; USER DEFINABLE ROUTINES.
; CALLED FROM MONITOR BY:-
; U XXXX ;DEFINE USER CALL ADDRESS.
; U <SP> ;GO TO USER ADDRESS.
; (IF XXXX=0 THEN USER CALL IS CLEARED)
;
USER:
CALL BLANK ;PUT IN A SPACE,
CALL GHXW ;THEN GO FOR THE ADDRESS, IF ANY.
JC USER2 ;SEE IF CARRY SET (BAD DATA?)
SHLD USERA ;NO. ADDRESS SET.
JMP NEXT
USER2:
CPI ' ' ;CARRY SET. SEE IF USER CALL REQUEST.
JNZ ILLEG ;IF NOT, PANIC
LHLD USERA ;YES. GET THE ADDRESS.
MOV A,L ;NOW SEE IF LEGAL ADDRESS BY
ORA H ;LOOKING FOR NON-ZERO ADDRESS.
JZ ILLEG
PCHL ;ALL O.K. GO THERE.
;
;
;
; ROUTINES TO PUNCH AND LOAD MEMORY.
; INTEL STANDARD HEX OBJECT TAPE FORMAT IS USED.
;
; RECORD START :
; BYTE COUNT 2-CHARS
; LOAD ADR 4-CHARS
; RECORD TYPE 2-CHARS 0=DATA 1=EOF
; DATA BYTES (2-CHARS/BYTE)
; CHECKSUM FROM BYTE-COUNT TO END OF DATA
; (ALL CHARACTERS MUST BE HEX LEGITIMATE 0-9,A-F)
;
; EOF RECORD MAY CONTAIN EXECUTION ADR.
; LOADER GOES TO ADR IF NON-ZERO
;
PUNCH:
CALL PUWA ;FROM ADR
CALL PUWA ;TO ADR
CALL PWAIT ;AWAIT READINESS
;
; HL=FIRST ADR DE=LAST ADR
;
PN0:
MOV A,L ;GET LOW PART OF START ADR
ADI OSET ;INCREMENT BY 8/16
MOV C,A ;HOLD IN 'C'
MOV A,H ;GET HIGH PART OF START ADR
ACI 0 ;TAKE CARE OF ANY O'FLOW
MOV B,A ;HOLD IN 'B'
MOV A,E ;NOW LOW PART OF FINAL ADR
SUB C ;SUBTRACT LOW START
MOV C,A ;PUT IN 'C'
MOV A,D ;HIGH PART END ADR.
SBB B ;SUBTRACT FROM START.
JC PN1 ;JUMP IF <OSET LEFT.
MVI A,OSET
JMP PN2
PN1:
MOV A,C ;SET UP FINAL COUNT.
ADI OSET+1 ;WENT NEGATIVE, ADD 9/17
PN2:
ORA A ;SET FLAGS.
JZ PDONE
PUSH D ;SAVE HI
MOV E,A ;LENGTH IN E
CALL PN3 ;PUNCH HEADER RECORD PARTS.
JMP PN4
PN3:
CALL CCRLF
MVI D,0 ;CLEAR CKSUM COUNTER.
MVI A,':' ;PUNCH HEADER
CALL CTYPE
MOV A,E
CALL PBYTE ;PUNCH LENGTH
MOV A,H
CALL PBYTE ;PUNCH ADR HI
MOV A,L
JMP PBYTE ;PUNCH ADR LO
PN4:
XRA A ;CLEAR A
CALL PBYTE ;RECORD TYPE=0
PN5:
MOV A,M ;GET DATA
INX H
CALL PBYTE ;FOR PUNCHING
DCR E ;DROP COUNT BY 1
JNZ PN5 ;NOT DONE YET
XRA A ;NOW FIND CKSUM
SUB D ;AS 2'S COMPL OF 8-BIT SUM
CALL PBYTE ;PUNCH IT
POP D ;RESTORE HI ADR
JMP PN0 ;GO AGAIN
;
; BYTE PUNCHER.
;
PBYTE:
PUSH PSW ;HOLD ONTO A,PSB
CALL CSTS ;SEE IF USER PANICED.
JNZ NEXT
POP PSW ;IF NOT, GO ON.
CALL CTHXB
ADD D ;UPDATE CKSUM
MOV D,A
RET ;GO AGAIN
;
; ALL DONE NOW.
;
PDONE:
CALL CCRLF
PDON1:
JMP NEXT ;RETURN TO MOMMA
;
; PUNCH AN END OF FILE.
;
PEND:
CALL PUWB ;ADR OR CR
JNC PEND1 ;GO IF ADR
LXI H,0 ;ASSUME CR, PUT ADR=0
CPI CR ;WAS IT CR?
JNZ ILLEG ;IF NOT, ITS ILLEGAL
PEND1:
CALL PWAIT ;AWAIT PROMPT
MVI E,0 ;ZERO LENGTH
CALL PN3
MVI A,1 ;RECORD TYPE=1
CALL PBYTE
XRA A
SUB D ;CALCULATE THE CKSUM
CALL PBYTE ;PUNCH IT.
;
; PUNCH 100 NULLS
;
NULLS:
MVI C,100 ;WE WILL PUNCH 100 NULLS (10 INCHES)
XRA A
NLS1:
CALL CTYPE
DCR C
JNZ NLS1 ;MORE TO GO?
JMP PDON1 ;NO. RETURN
;
NULL:
CALL PWAIT ;THIS ENTRY VIA COMMAND 'N'
JMP NULLS ;FOLLOWED RAPIDLY BY NULLS.
;
; LOAD HEX OBJECT TAPE.
;
; MONITOR COMMAND 'L'
; LOAD A HEX-BINARY TAPE AS PRODUCED BY THE 'P'
; COMMAND.
; MAY CONTAIN AN OFFSET VALUE, ALLOWING THE DATA TO
; BE LOADED INTO A DIFFERENT LOCATION TO THAT SPECIFIED
; BY THE LOAD ADDRESS.
; E.G. L 1000 WILL CAUSE THE LOADED DATA TO BE
; 1000H LOCATIONS HIGHER THAN THAT SPECIFIED BY
; THE BLOCK LOAD ADDRESS.
;
;
LOAD:
CALL PUWB ;GET THE OFFSET, IF ANY.
JNC LD4
CPI CR ;ERROR MAY ONLY BE <CR>
JNZ ILLEG
LD4:
XRA A ;PREPARE TO
CALL ECHCN ;RESET ECHO.
CALL CRLF ;NEW LINE PLEASE.
PUSH H ;SAVE BIAS ADR
LD5:
POP H ;GET BIAS
PUSH H ;AND RESTORE
CALL RIX ;GET INPUT
MVI B,':' ;WAIT FOR ':'
SUB B
JNZ LD5 ;TRY AGAIN
MOV D,A ;CLEAR CKSUM
CALL BYTE ;GET LENGTH
JZ LD7 ;ZERO MEANS ALL DONE
MOV E,A ;SAVE LENGTH
CALL BYTE
PUSH PSW ;SAVE HI ADR
CALL BYTE
POP B ;FETCH MSBYTE
MOV C,A ;BC NOW HAS ADR
PUSH B ;SAVE IT
XTHL ;INTO HL
SHLD BLKAD ;SAVE BLOCK ADR
XTHL ;IN CASE OF ERROR
POP B
DAD B ;RESTORE AND ADD BIAS
CALL BYTE ;RECORD TYPE INPUT
LD6:
CALL BYTE ;GET DATA BYTES
CALL STORE ;STORE
INX H
DCR E
JNZ LD6 ;GO ON.
CALL BYTE ;GET CKSUM
JZ LD5
LDERR:
LXI H,M6 ;CKSUM ERROR
CALL MSG
LHLD BLKAD ;ADR OF THIS BLOCK IS
JMP RXAR ;NOW GIVEN
LD7:
CALL BYTE ;MSB OF XEQAD
MOV H,A
CALL BYTE
MOV L,A
ORA H
JZ NEXT ;MONITOR IF ADR=0
PCHL ;OTHERWISE EXECUTE
;
RIX:
CALL RI
JC ILLEG ;ON ERROR, PRINT '??'
ANI 7FH ;REMOVE PARITY
RET
;
; ROUTINE RI
; GETS A CHARACTER FROM THE CASSETTE READER INPUT
;
;
RI:
PUSH B ;SAVE BC
LXI B,TMOUT ;GET TIMEOUT (MILLISECONDS)
RI10:
CALL CASTS ;GET READER STATUS
JNZ RI15 ;READY ON NON-ZERO
CALL DELAY ;IF NOT, DELAY 1 MS
DCX B ;DECREMENT DELAY COUNT
MOV A,B ;SEE IF IT
ORA C ;IS ZERO YET.
JNZ RI10 ;TRY AGAIN IF NOT DONE
STC ;SET ERROR CARRY
POP B ;RESTORE BC
RET ;TROUBLED RETURN
RI15:
CALL CGETCH ;GET DATA.
ORA A ;CLEAR CARRY ONLY.
POP B ;RESTORE BC
RET ;SIMPLY RETURN
;
BYTE:
PUSH B ;SAVE BC
CALL RIX ;READ ASCII
CALL CNVBN ;CONVERT TO HEX
JC LDERR ;ERROR DETECTOR.
RLC ;SHIFT LEFT 4 BITS
RLC
RLC
RLC
MOV B,A ;SAVE THEM A WHILE
CALL RIX ;GET SECOND BYTE
CALL CNVBN ;CONVERT TO HEX
JC LDERR ;ERROR DETECTOR
ORA B ;OR IN THE SAVED NYBBLE
MOV C,A ;HOLD BYTE A WHILE.
ADD D ;ADD TO CKSUM
MOV D,A ;UPDATE CKSUM
MOV A,C ;RESTORE BYTE
POP B ;RESTORE BC
RET
;
; FUNCTION DELAY.
; CAUSES THE SYSTEM TO DELAY FOR 1 MS.
;
DELAY:
PUSH B ;SAVE BC
MVI B,ONEMS ;GET ONE MS LOOP COUNT
DEL2:
DCR B ;DECREMENT LOOP COUNT
JNZ DEL2 ;NOT YET DONE.
POP B ;ALL DONE. GET BC
RET ;RETURN TO PATIENT WAITER.
; ENTER HERE FOLLOWING A SOFTWARE RST2
; I.E. BREAKPOINT SETTING.
;
BPAT:
SHLD SVPC ;STORE CALLING PC
STA TMPA ;AND CARRY (IN B7)
RAL ;THEN ROTATE BACK THE ACC.
LXI H,0 ;NOW TRANSFER THE SP TO HL BY DOING A DUMMY
DAD SP ;ADD TO HL. (N.B. CLEARS CARRY)
SHLD SVSP ;SAVE THE CALLER SP.
LXI SP,SVA+1 ;PICK UP REG STORE POINTER
PUSH PSW ;TO SAVE PSW
PUSH B ;AND BC
PUSH D ;AND DE. (HL ALREADY SAVED)
LXI H,SVF ;GET THE PSB BYTE
LDA TMPA ;PICK UP THE CARRY HOLDER,
RAL ;ROTATE IT BACK TO CARRY.
JNC BP1 ;SKIP IF CARRY NOT SET,
INR M ;OTHERWISE RESET CARRY.
BP1:
LXI SP,STACK ;SET SP TO MONITOR STACK
LXI H,M10 ;TYPE BREAKPOINT MESSAGE
CALL MSG
LHLD SVPC ;PICK-UP THE BREAK ADDRESS + 1
DCX H ;MAKE IT THE REAL ADDRESS.
SHLD SVPC ;RESET THE SAVED PC STORE
CALL THXW ;TELL THE USER WHERE HE BROKE.
CALL CRLF ;NEXT LINE PLEASE.
JMP REXAL ;NOW PRINT THE REGISTER DATA.
;
;
;
; CONTINUE AFTER A BREAKPOINT HALT
;
; ASSUMES THAT THE LOCATION OF THE B/P HAS BEEN ALTERED
; BY A PRIOR
; B XXXX COMMAND.
; CONTINUE CAN ONLY BE USED TO RETURN THE MONITOR TO
; A PROGRAM WHICH HAS BEEN HALTED BY EXECUTION
; OF A 'RST 2' INSTRUCTION (0D7H) AT A LOCATION WHOSE CONTENTS
; ARE SAVED IN 'BPDAT'.
;
CONT:
LHLD SVPC ;GET PSEUDO-RESTART.
MOV A,L ;PUT LOW PART IN ACC.
ORA H ;RESULT WILL BE ZERO IF ALL
JZ ILLEG ;BITS ARE ZERO. I.E. NO B/P.
CALL BLANK ;PRINT A SPACE
CALL THXW ;FOLLOWED BY THE ADDRESS.
XCHG ;PUT OLD ADDRESS IN DE
LHLD BPADD ;NOW GET CURRENT ADDRESS.
CALL NEGDE ;NEGATE THE PC ADDRESS.
DAD D ;D.P. ADD TO B/P ADDRESS.
MOV A,L ;LO RESULT TO ACC,
ORA H ;OR IT WITH HI RESULT,
LHLD SVPC ;RECOVER PC (MAY NEED IT)
JNZ CON3 ;SEE IF DE=HL (I.E. ZERO RESULT)
LXI H,BPDAT ;GET START ADDRESS OF SAVED INSTRUCTION.
CON3:
MVI A,CR ;<CR> FORCES 'J' CONTINUE.
PUSH PSW ;SAVE SIMULATED 'J' COMMAND
JMP JMP4 ;NOW ENTER 'JUMP'.
;
;
; BREAK-POINT THE PROGRAM AT LOCATION XXXX
; B XXXX
;
; MAY ALSO BE USED TO CLEAR A PREVIOUS B/P BY
; B (CRTN)
;
; BPT SAVES THE ADDRESS XXXX AND ITS CONTENTS
; IT THEN REPLACES THE CONTENTS OF XXXX WITH D7 ( RST 2 ).
; THIS FORCES THE PROGRAM TO SAVE ALL DATA AND RETURN
; TO THE MONITOR. THE PROGRAM MAY BE RESTARTED FROM
; XXXX BY A CONTINUE ( C ) COMMAND AFTER IT HAS HALTED.
;
BPT:
;
;**** THIS CONDITIONAL CODE INSERTS THE RST2 JUMP IN RAM IF
; THE MONITOR IS NOT IN PAGE ZERO.
;
; ORG 0010H
; JMP BPIN
;
IF ROMSW
MVI A,JMP ;GET A 'JMP'
STA 0010H ;PUT IT AT 0010H
LXI H,BPIN ;GET ADDRESS OF 'BPIN'
SHLD 0011H ;STORE IT AT 0011H
ENDIF
CALL PUWB ;GET ADDRESS
JNC BPT1 ;GOT AN ADDRESS - SO PROCEED
CPI CR ;NOT AN ADDRESS - WAS IT A CRTN
JNZ ILLEG ;NO SO BOMB OUT
LXI H,0 ;YES SO SIMULATE AN ADDRESS OF ZERO
;
; BPT WILL REMOVE THE OLD B/P (IF ANY )
;
BPT1:
PUSH H ;COME HERE WITH ADDRESS IN HL. SAVE IT ON THE STACK
LHLD BPADD ;IS THE PREVIOUS B/P ADDRESS = 0
MOV A,L ;PUT LO PART OF ADDRESS IN ACC
ORA H ;THEN 'OR' WITH HI PART
JZ BPT2 ;IT WAS ZERO SO SAVE XXXX AND (XXX)
LXI H,BPDAT ;POINT TO THE SAVED DATA FROM THE LAST B/P
MOV A,M ;GET IT IN A
LHLD BPADD ;GET THE LAST B/P ADDRESS IN HL
CALL STORE ;AND RESTORE THE DATA THERE
;
; BREAKPOINT MAKER.
; CREATES A GAP IN THE TARGET PROGRAM BY INSERTING AN 'RST 2'
; IN PLACE OF THE FIRST BYTE OF THE INSTRUCTION.
; THE INSTRUCTION (ALL BYTES, COUNT COMPUTED) IS PLACED
; IN A TEMPORARY STORE, ALONG WITH A JUMP TO THE NEXT
; INSTRUCTION IN THE TARGET PROGRAM.
;
BPT2:
POP H ;RETRIEVE B/P ADDRESS FROM STACK.
SHLD BPADD ;SAVE IT FOR FUTURE RETURN.
MOV A,H ;SEE IF THIS IS
ORA L ;ONLY CLEARING
JZ NEXT ;THE BREAKPOINT.
MOV A,M ;LOAD ITS FIRST BYTE.
LXI H,TAB1 ;GET START ADDRESS OF TABLE 1
CPI 40H ;SEE IF THE BYTE IS IN TABLE 1
JC BPT3 ; I.E. LESS THAN 40H
LXI H,TAB2 ;GET START OF TABLE 2.
SUI 0C0H ;SEE IF IT IS IN TABLE 2
JNC BPT3 ; I.E. >0BFH
MVI A,1 ;THE GROUP 40H TO 0BFH IS 1-BYTE
JMP BPT5 ;IN LENGTH.
BPT3:
MOV D,A ;RANGE OF BYTE IS NOW 0 TO 64
RRC ;WE MUST PACK THIS RANGE DOWN
RRC ;TO 0 TO 15 BYTES OFFSET.
MVI B,0 ;AND THEN MAKE UP THE
ANI 0FH ;TRUE ADDRESS BY
MOV C,A ;ADDING THE OFFSET TO THE
DAD B ;START ADDRESS IN THE TABLE.
MVI A,3 ;WE MUST ALSO KNOW WHERE IN
ANA D ;THE BYTE THE INSTRUCTION SIZE
MOV D,A ;IS TO BE FOUND. (SEE NOTE ABOVE TABLE)
MOV A,M ;GET THE KEY BYTE.
BPT4:
DCR D ;FIND THE KEY POSSY.
JM BPT5 ;BY DECREMENTING THE 'D' REGISTER UNTIL IT
RRC ;GOES NEGATIVE. IF NOT FOUND, ROTATE THE KEY
RRC ;BYTE 2 POSITIONS RIGHT
JMP BPT4 ;AND TRY AGAIN
BPT5:
ANI 3 ;WE CAN NOW COMPUTE THE BYTE COUNT.
JZ ILLEG ;(OF COURSE 0 IS ILLEGAL)
MOV C,A ;SAVE THE COUNT IN C
LXI H,BPDAT ;DATA STORE ADDRESS
XCHG ;PUT IT INTO DE
LHLD BPADD ;GET THE SOURCE ADDRESS.
BPT6:
MOV A,M ;PICK UP THE DATA BYTE AND
INX H ;THEN BUMP ADDRESS.
XCHG ;AFTER SWAPPING HL ADDRESSES,
MOV M,A ;PUT IT IN THE BUFFER.
INX H ;NOW BUMP STORE ADDRESS,
XCHG ;BEFORE RESTORING THE ADDRESSES.
DCR C ;DECREMENT BYTE COUNTER.
JNZ BPT6 ;TRY AGAIN IF STILL DATA.
XCHG ;RETRIEVE THE STORE ADDRESS.
MVI M,JMP ;PUT 'JMP' (0C3H) IN STORE.
INX H ;BUMP STORE ADDRESS.
MOV M,E ;LOW ORDER RETURN ADDRESS.
INX H ;BUMP YET AGAIN.
MOV M,D ;HIGH ORDER RETURN ADDRESS.
LHLD BPADD ;FINALLY REPLACE THE
MVI M,0D7H ;B/P WITH AN 'RST 2'
JMP NEXT
;
; BREAKPOINT DATA TABLE.
; CONSISTS OF A SERIES OF DATA BYTES WHICH DEFINE THE
; NUMBER OF BYTES IN AN INSTRUCTION, BASED ON THE
; VALUE OF ITS FIRST BYTE.
;
; THE TABLE HAS 2 SECTIONS.
; TAB1 CONTAINS DATA FOR BYTES 000H TO 03FH
; TAB2 CONTAINS DATA FOR BYTES 0C0H TO 0FFH
; EACH BYTE CONTAINS 4 KEYS REPRESENTING THE SIZE OF
; 4 INSTRUCTIONS (RANGE 0-3, 0 IS ILLEGAL)
; SUCH THAT THE BOTTOM 2 BITS OF THE INSTRUCTION BYTE KEY TO
; THE TABLE BYTE AS FOLLOWS:-
; 00 BITS B1,B0
; 01 BITS B3,B2
; 10 BITS B5,B4
; 11 BITS B7,B6
;
B00 EQU 0 ;KEY 0 DATA BITS
B01 EQU 1
B02 EQU 2
B03 EQU 3
B10 EQU 0 ;KEY 1 DATA BITS
B11 EQU B01*4
B12 EQU B02*4
B13 EQU B03*4
B20 EQU 0 ;KEY 2 DATA BITS
B21 EQU B11*4
B22 EQU B12*4
B23 EQU B13*4
B30 EQU 0 ;KEY 3 DATA BITS
B31 EQU B21*4
B32 EQU B22*4
B33 EQU B23*4
;
TAB1:
DB B01+B13+B21+B31
DB B01+B11+B22+B31
DB B00+B11+B21+B31
DB B01+B11+B22+B31
DB B00+B13+B21+B31
DB B01+B11+B22+B31
DB B00+B11+B21+B31
DB B01+B11+B22+B31
DB B01+B13+B23+B31
DB B01+B11+B22+B31
DB B00+B11+B23+B31
DB B01+B11+B22+B31
DB B01+B13+B23+B31
DB B01+B11+B22+B31
DB B00+B11+B23+B31
DB B01+B11+B22+B31
TAB2:
DB B01+B11+B23+B33
DB B03+B11+B22+B31
DB B01+B11+B23+B30
DB B03+B13+B22+B31
DB B01+B11+B23+B32
DB B03+B11+B22+B31
DB B01+B10+B23+B32
DB B03+B10+B22+B31
DB B01+B11+B23+B31
DB B03+B11+B22+B31
DB B01+B11+B23+B31
DB B03+B10+B22+B31
DB B01+B11+B23+B31
DB B03+B11+B22+B31
DB B01+B11+B23+B31
DB B03+B10+B22+B31
;
;**** CASSETTE I/O HANDLING ROUTINES.
;
;
;**** CASSETTE OUTPUT CHARACTER.
;
CTYPE:
PUSH PSW ;SAVE PSW
CTYP1:
IN CSST ;STATUS
ANI TRDY ;READY?
JZ CTYP1
POP PSW ;YES. PRINT
OUT CSOUT ;AT CASSETTE.
RET
;
;**** GET CHARACTER
;
CSI:
CGETCH:
CALL CASTS ;GET STATUS
JZ CSI
IN CSIN ;GET CHR
RET
;
;**** CASSETTE INPUT STATUS
;
CASTS:
IN CSST ;STATUS BYTE
ANI RBR ;MASKED
RET
;
;**** CASSETTE BYTE PUT.
;
CTHXB:
PUSH PSW ;SAVE DATA
RRC ;ROTATE
RRC ;THE
RRC ;BYTE
RRC ;4 BITS.
CALL CTHXN ;PRINT 1ST NYBBLE
POP PSW ;RECOVER
;
;**** CASSETTE NYBBLE PUT.
;
CTHXN:
PUSH PSW ;SAVED
ANI 0FH ;BOTTOM 4 BITS
ADI 90H ;MAKE THE
DAA ;NYBBLE
ACI 40H ;INTO AN
DAA ;ASCII CHR 0-F
CALL CTYPE ;PUT IT.
POP PSW
RET
;
;**** CASSETTE WORD OUTPUT.
;
CTHXW:
PUSH PSW ;SAVE PSW
MOV A,H ;DO TOP
CALL CTHXB ;BYTE
MOV A,L ;THEN BOTTOM
CALL CTHXB ;BYTE
POP PSW
RET
;
;**** CASSETTE CRLF OUTPUT.
;
CCRLF:
PUSH H ;SAVE HL
LXI H,M2 ;GET MESSAGE
CALL CMSG ;PRINT IT.
POP H
RET
;
;**** CASSETTE MESSAGE.
;
CMSG:
PUSH PSW
PUSH H ;SAVE PSW AND HL
CMNXT:
MOV A,M ;GET BYTE
INX H ;BUMP PTR.
CPI 0FFH ;END FLAG?
CNZ CTYPE
JNZ CMNXT ;MORE.
POP H ;RECOVER HL
POP PSW ;AND PSW
RET
;
;**** CASSETTE BLANK.
;
CBLANK:
PUSH PSW
MVI A,' ' ;A SPACE
CALL CTYPE ;IS SENT.
POP PSW
RET
;
;**** GET HEX NYBBLE.
;
CGHXN:
MVI A,0FH ;ONLY BOTTOM NYBBLE
JMP CGHB1
;
;**** GET HEX BYTE.
;
CGHXB:
MVI A,0FFH ;ALL BYTE NEEDED.
CGHB1:
PUSH H ;SAVE HL
CALL CGHXW ;GET A WORD.
JC CGHB2 ;ERROR?
ANA L ;NYBBLE/BYTE ONLY.
CGHB2:
POP H
RET
;
;**** GET HEX WORD FROM CASSETTE.
;
CGHXW:
PUSH PSW ;SAVE PSW
LXI H,0 ;START WITH NOTHING.
CALL CGETCH ;GET CHARACTER
ANI 7FH ;AND MASK IT.
CALL CNVBN ;CONVERT TO BINARY.
JC GHW3
MOV L,A ;SAVE IT IF O.K.
CGHW1:
CALL CGETCH ;AND ANOTHER
ANI 7FH ;MASKED.
CALL CNVBN ;THEN CONVERTED.
JC GHW2
DAD H ;*2
DAD H ;*4
DAD H ;*8
DAD H ;*16
ADD L ;ADD LO BYTE.
MOV L,A ;UPDATE
JMP CGHW1
;
;
;
;
;
ORG ROM + 07DCH
;
;**** JUMP TABLE FOR CASSETTE ROUTINES.
;
ZCTYPE: JMP CTYPE
ZCGETC: JMP CGETCH
ZCMSG: JMP CMSG
ZCCRLF: JMP CCRLF
ZCSPAC: JMP CBLANK
ZCTHXN: JMP CTHXN
ZCTHXB: JMP CTHXB
ZCTHXW: JMP CTHXW
ZCGHXN: JMP CGHXN
ZCGHXB: JMP CGHXB
ZCGHXW: JMP CGHXW
ZCASTS: JMP CASTS
;
ORG ROM+0800H
;
QIN: EQU 0DBH
QOUT: EQU 0D3H
QRET: EQU 0C9H
;
;**** INPUT AND OUTPUT PORT DATA ROUTINES.
;
INPT:
OUTPT:
MVI A,QIN ;ASSUME 'IN' COMMAND
STA BUFF
CALL GBYTE ;GET PORT NUMBER.
STA BUFF+1 ;SAVE IT IN 'BUFF+1'
MVI A,QRET ;GET 'RET'
STA BUFF+2
MVI A,'I' ;SEE IF THIS IS 'IN' COMMAND.
CMP B
JNZ OUTER ;MUST BE 'OUT'
CALL BUFF ;GET INPUT DATA.
CALL BLANK ;ONE SPACE,
CALL THXB ;FOLLOWED BY THE BYTE.
CALL CRLF
JMP NEXT
OUTER:
MVI A,QOUT ;REPLACE 'IN' WITH 'OUT'
STA BUFF
CALL GBYTE ;OUTPUT BYTE REQUIRED.
CALL CRLF
CALL BUFF ;OUTPUT IT.
JMP NEXT
;
;
;***********************************************************
;
; DISASSEMBLER PROGRAM FOR 8080 ROUTINES.
;
;***********************************************************
;
;
;**** FIND START ADDRESS.
;
DIS80:
CALL PUWB ;GET START ADDRESS.
JC ILLEG ;ERROR EXIT
CALL CRLF
MOV B,H
MOV C,L ;BC NOW HAS MEMORY ADDR.
;
;**** GET BYTE.
;
DIS1:
MOV H,B ;PUT MEMORY ADDRESS
MOV L,C ;INTO HL
CALL THXW ;PRINT IT
CALL BLANK ;AND A SPACE.
LDAX B ;GET FIRST BYTE.
;
;**** FIND THE TABLE POSITION.
;
MOV E,A ;PUT OFFSET INTO C
MVI D,0 ;AND CLEAR HI BYTE
;
; ADD OFFSET THREE TIMES.
;
LXI H,ATAB1 ;TABLE START ADDRESS.
DAD D ;ADD OFFSET
DAD D ;THREE
DAD D ;TIMES.
;
;**** READY TO PROCESS.
;
MOV D,M ;LOAD BYTE COUNT.
MOV A,D
INX H ;BUMP PAST BYTE COUNTER.
CALL BPRNT ;PRINT THE BYTES.
MOV E,M ;GET OPCODE OFFSET
MVI D,0 ;INTO DE
INX H ;BUMP TABLE POINTER.
PUSH H ;AND SAVE IT
LXI H,ATAB2 ;ADD OFFSET
DAD D ;TO THE
DAD D ;TABLE HEADER
DAD D ;FOUR
DAD D ;TIMES.
MVI D,4
CALL PRNT ;PRINT OPCODE.
LXI H,MSGBK ;NOW PRINT
CALL MSG ;4 SPACES
POP H ;RETRIEVE PTR.
MOV E,M ;DITTO FOR OPERAND(S).
MVI D,0
LXI H,ATAB3
DAD D
DAD D
DAD D
MVI D,3
CALL PRNT ;PRINT OPERAND(S)
PUSH B ;SAVE MEM PTR.
MVI H,0 ;ZERO OUT H
MOV L,A ;PUT BYTE COUNT INTO L
DAD B ;BUMP MEMORY ADDRESS.
MOV B,H ;PUT BACK INTO
MOV C,L ;BC
POP H ;RETRIEVE MEMORY ADDRESS.
DCR A ;TEST BYTE COUNT
JZ DISB1 ;FOR ONE
DCR A
JZ DISB2 ;OR TWO
DISB3:
INX H ;GET AND
MOV E,M ;PRINT
INX H ;16 BIT
MOV D,M ;DATA
XCHG ;WORD
CALL THXW ;VALUE
JMP DISB1
DISB2:
INX H ;GET AND
MOV A,M ;PRINT 8 BIT
CALL THXB ;DATA BYTE VALUE
DISB1:
CALL CRLF ;NEW LINE PLEASE.
CALL HOLD ;SEE IF HOLD REQUESTED.
JMP DIS1 ;NO.
;
;**** PRINT CURRENT BYTE IF VALID.
;
BPRNT:
PUSH PSW ;SAVE PSW.
PUSH B ;SAVE CURRENT MEM PTR.
MVI E,3 ;PRINT 3 BYTES.
BPRT1:
LDAX B ;GET CURRENT MEMORY BYTE.
DCR D ;DECREMENT COUNTER.
CP THXB ;PRINT IT,
CM BLANK ;OR ELSE 2 SPACES.
CM BLANK
CALL BLANK ;FOLLOWED BY SPACER.
INX B ;FINALLY BUMP POINTER.
DCR E
JNZ BPRT1
POP B ;RETRIEVE MEM PTR.
POP PSW ;AND PSW.
RET
;
;**** PRINT A STRING FOLLOWED BY A SPACE.
;
PRNT:
PUSH PSW
PRNT1:
MOV A,M ;GET DATA BYTE
CALL TYPE ;PRINT IT.
INX H ;READY FOR NEXT BYTE
DCR D ;DECREMENT AND TEST
JNZ PRNT1 ;LOOP COUNT.
CALL BLANK
POP PSW
RET
;
;
;********************************************************
;
; LINE ASSEMBLER PROGRAM.
; USES COMMON TABLES WITH DISASSEMBLER.
;
;********************************************************
;
;
ASM80:
CALL PUWB ;GET START ADDRESS.
JC ILLEG
CALL CRLF
ASM1:
CALL THXW ;TYPE CURRENT ADDRESS.
SHLD MEMADR ;SAVE CURRENT ADDRESS.
CALL STRING ;GET THE OPCODE STRING.
LXI H,ATAB2 ;OPCODE TABLE
MVI B,4 ;HAS 4 BYTES/ENTRY
CALL STCOMP ;SCAN FOR THE GIVEN STRING.
JC ILLEG ;CARRY SET ON ERROR.
STA OPCODE ;SAVE OPCODE OFFSET.
LXI H,ATAB1+1 ;FIND A CODE
ASM2:
CMP M ;WHICH MATCHES
INX H ;SO THAT
JZ ASM3 ;WE CAN SEE
INX H ;IF THE
INX H ;THIRD BYTE IN
JMP ASM2 ;THE TABLE
ASM3:
MOV A,M ;HAPPENS TO BE
CPI 0 ;NON-ZERO.
JZ ASM4 ;I.E. NON-BLANK
CALL STRING ;OPERAND STRING REQUIRED.
LXI H,ATAB3 ;LOOK FOR OPERAND STRING
MVI B,3 ;IN 3 BYTE/ENTRY OPERAND
CALL STCOMP ;TABLE.
JC ILLEG
CALL BLANK ;SPACE UP
ASM4:
MOV E,A ;SAVE OPERAND CODE NUMBER
LDA OPCODE ;AND ALSO
MOV D,A ;OPCODE CODE NUMBER
LXI H,ATAB1+1 ;FIND DOUBLE MATCH
MVI C,0 ;IN THE OPCODE TABLE
ASM5:
MOV A,M ;GET TEST BYTE.
CPI 0FFH ;SEE IF E.O.T.
JZ ILLEG ;I.E. -1 BYTE.
CMP D ;OPCODE MATCH?
JNZ ASM6
INX H
MOV A,M
CMP E ;OPERAND MATCH?
JZ ASM7
DCX H
ASM6:
INX H ;NO. BUMP
INX H ;PAST THIS
INX H ;ENTRY AND
INR C ;INCREMENT TABLE COUNTER.
JMP ASM5
ASM7:
DCX H ;GOT IT. GO BACK
DCX H ;TWO BYTES AND
MOV D,M ;GET BYTE COUNT.
LHLD MEMADR ;RETRIEVE CURRENT MEM ADDR.
MOV A,C ;STORE THE FIRST
CALL STORE ;BYTE VALUE
MOV A,D ;THEN LOOK AT
SUI 2 ;SIZE OF INSTRUCTION.
JM ASB1 ;ONE BYTE
LXI H,MSGBK ;OR MULTIBYTE.
CALL MSG
CALL GHXW ;GET A NUMBER.
JC ILLEG
ORA A ;RESET BYTE FLAG.
JZ ASB2 ;TWO BYTE.
ASB3:
XCHG ;NUMBER NOW IN DE.
LHLD MEMADR ;GET MEMOR ADDR.
INX H ;PUT LO BYTE
MOV A,E ;INTO NEXT
CALL STORE ;ADDRESS.
INX H ;AND HI BYTE
MOV A,D ;INTO 3RD BYTE
CALL STORE ;ADDRESS.
JMP ASB1 ;FINISH OFF.
ASB2:
MOV A,L ;PUT LO BYTE
LHLD MEMADR ;ONLY INTO
INX H ;INTO 2ND. BYTE
CALL STORE ;ADDRESS.
ASB1:
INX H ;BUMP TO NEXT ADDR.
CALL CRLF ;NEW LINE,
JMP ASM1 ;START ALL OVER AGAIN.
;
;**** STRING INPUT ROUTINE.
; ON RETURN, FIRST 4 BYTES IN 'BUFF' WITH
; TRAILING BLANKS IF NECESSARY.
;
STRING:
LXI H,MSGBK
CALL MSG
LXI H,2020H ;PUT SPACES
SHLD BUFF ;INTO 4 BYTE
SHLD BUFF+2 ;BUFFER.
LXI H,BUFF
MVI E,4
STR1:
CALL CHIN ;LOOK FOR
CPI CR ;<CR> TERMINATOR
JZ NEXT
JMP STR3
STR2:
CALL CHIN ;GET A CHARACTER.
STR3:
CPI CR ;LOOK FOR
RZ ;<CR> OR
CPI ' ' ;SPACE AS
RZ ;DELIMITER.
DCR E ;ONLY THE FIRST
JM STR2 ;4 BYTES
MOV M,A ;ARE STORED.
INX H
JMP STR2
;
;**** STRING COMPARE ROUTINE.
; ON INPUT, HL=START OF TEST TABLE
; B=BYTE COUNT PER ENTRY.
; GOOD OUTPUT, CARRY CLI, ACC=OFFSET VALUE.
; BAD OUTPUT, CARRY SET, ACC=0FFH.
;
STCOMP:
MVI C,0 ;CLEAR COUNTER.
STC0:
PUSH B ;SAVE COUNTER AND STRING SIZE.
LXI D,BUFF ;GET BUFFER START.
STC1:
LDAX D ;GET TEST BYTE.
CMP M ;SEE IF DIFFERENT.
JNZ STC2
DCR B ;OR IF ALL BYTES CHECK.
JZ STC5
INX D ;BUMP POINTERS
INX H ;AND THEN
JMP STC1 ;TRY AGAIN.
STC2:
MOV A,M ;DIFFERENT. SAVE CURRENT BYTE.
STC3:
DCR B ;BUMP
INX H ;PAST
JZ STC4 ;THIS
JMP STC3 ;BYTE.
STC4:
POP B ;RETRIEVE COUNTERS,
INR C ;BUMP COUNTER,
CPI 0FFH ;SEE IF E.O.T.
JZ STC6
JMP STC0 ;TRY AGAIN.
STC5:
POP B ;FOUND A MATCH.
MOV A,C ;RETURN ENTRY
ORA A ;IN ACC WITH
RET ;CARRY RESET.
STC6:
STC ;ERROR RETURN
RET ;SETS CARRY ONLY.
;
MSGBK: DB ' ',0FFH
;
;**** OPERATION CODE TABLE.
; ARRANGED AS FOLLOWS, ACCORDING TO INSTRUCTION
; FIRST BYTE VALUE (0-255):-
;
; FIRST BYTE IS INSTRUCTION SIZE (BYTES)
; NEXT 4 BYTES ARE OPCODE.
; NEXT BYTE IS ATAB3 ENTRY NUMBER.
;
ATAB1:
DB 1,0,0
DB 3,1,1
DB 1,2,1
DB 1,6,1
DB 1,8,1
DB 1,9,1
DB 2,30,1
DB 1,10,0
DB 1,88,0
DB 1,14,1
DB 1,3,1
DB 1,7,1
DB 1,8,2
DB 1,9,2
DB 2,30,2
DB 1,11,0
DB 1,88,0
DB 3,1,3
DB 1,2,3
DB 1,6,3
DB 1,8,3
DB 1,9,3
DB 2,30,3
DB 1,12,0
DB 1,88,0
DB 1,14,3
DB 1,3,3
DB 1,7,3
DB 1,8,4
DB 1,9,4
DB 2,30,4
DB 1,13,0
DB 1,85,0
DB 3,1,5
DB 3,4,0
DB 1,6,5
DB 1,8,5
DB 1,9,5
DB 2,30,5
DB 1,15,0
DB 1,88,0
DB 1,14,5
DB 3,5,0
DB 1,7,5
DB 1,8,6
DB 1,9,6
DB 2,30,6
DB 1,16,0
DB 1,86,0
DB 3,1,9
DB 3,17,0
DB 1,6,9
DB 1,8,7
DB 1,9,7
DB 2,30,7
DB 1,19,0
DB 1,88,0
DB 1,14,9
DB 3,18,0
DB 1,7,9
DB 1,8,8
DB 1,9,8
DB 2,30,8
DB 1,20,0
DB 1,21,11
DB 1,21,12
DB 1,21,13
DB 1,21,14
DB 1,21,15
DB 1,21,16
DB 1,21,17
DB 1,21,18
DB 1,21,19
DB 1,21,20
DB 1,21,21
DB 1,21,22
DB 1,21,23
DB 1,21,24
DB 1,21,25
DB 1,21,26
DB 1,21,27
DB 1,21,28
DB 1,21,29
DB 1,21,30
DB 1,21,31
DB 1,21,32
DB 1,21,33
DB 1,21,34
DB 1,21,35
DB 1,21,36
DB 1,21,37
DB 1,21,38
DB 1,21,39
DB 1,21,40
DB 1,21,41
DB 1,21,42
DB 1,21,43
DB 1,21,44
DB 1,21,45
DB 1,21,46
DB 1,21,47
DB 1,21,48
DB 1,21,49
DB 1,21,50
DB 1,21,51
DB 1,21,52
DB 1,21,53
DB 1,21,54
DB 1,21,55
DB 1,21,56
DB 1,21,57
DB 1,21,58
DB 1,21,59
DB 1,21,60
DB 1,21,61
DB 1,21,62
DB 1,21,63
DB 1,21,64
DB 1,76,0
DB 1,21,66
DB 1,21,67
DB 1,21,68
DB 1,21,69
DB 1,21,70
DB 1,21,71
DB 1,21,72
DB 1,21,73
DB 1,21,74
DB 1,22,1
DB 1,22,2
DB 1,22,3
DB 1,22,4
DB 1,22,5
DB 1,22,6
DB 1,22,7
DB 1,22,8
DB 1,23,1
DB 1,23,2
DB 1,23,3
DB 1,23,4
DB 1,23,5
DB 1,23,6
DB 1,23,7
DB 1,23,8
DB 1,24,1
DB 1,24,2
DB 1,24,3
DB 1,24,4
DB 1,24,5
DB 1,24,6
DB 1,24,7
DB 1,24,8
DB 1,25,1
DB 1,25,2
DB 1,25,3
DB 1,25,4
DB 1,25,5
DB 1,25,6
DB 1,25,7
DB 1,25,8
DB 1,26,1
DB 1,26,2
DB 1,26,3
DB 1,26,4
DB 1,26,5
DB 1,26,6
DB 1,26,7
DB 1,26,8
DB 1,27,1
DB 1,27,2
DB 1,27,3
DB 1,27,4
DB 1,27,5
DB 1,27,6
DB 1,27,7
DB 1,27,8
DB 1,28,1
DB 1,28,2
DB 1,28,3
DB 1,28,4
DB 1,28,5
DB 1,28,6
DB 1,28,7
DB 1,28,8
DB 1,29,1
DB 1,29,2
DB 1,29,3
DB 1,29,4
DB 1,29,5
DB 1,29,6
DB 1,29,7
DB 1,29,8
DB 1,42,0
DB 1,66,1
DB 3,43,0
DB 3,40,0
DB 3,44,0
DB 1,67,1
DB 2,31,0
DB 1,77,0
DB 1,45,0
DB 1,39,0
DB 3,46,0
DB 1,88,0
DB 3,47,0
DB 3,41,0
DB 2,32,0
DB 1,78,0
DB 1,48,0
DB 1,66,3
DB 3,49,0
DB 2,72,0
DB 3,50,0
DB 1,67,3
DB 2,33,0
DB 1,79,0
DB 1,51,0
DB 1,88,0
DB 3,52,0
DB 2,73,0
DB 3,53,0
DB 1,88,0
DB 2,34,0
DB 1,80,0
DB 1,54,0
DB 1,66,5
DB 3,55,0
DB 1,68,0
DB 3,56,0
DB 1,67,5
DB 2,35,0
DB 1,81,0
DB 1,57,0
DB 1,69,0
DB 3,58,0
DB 1,70,0
DB 3,59,0
DB 1,88,0
DB 2,36,0
DB 1,82,0
DB 1,60,0
DB 1,66,10
DB 3,61,0
DB 1,74,0
DB 3,62,0
DB 1,67,10
DB 2,37,0
DB 1,83,0
DB 1,63,0
DB 1,71,0
DB 3,64,0
DB 1,75,0
DB 3,65,0
DB 1,88,0
DB 2,38,0
DB 1,84,0
;
;**** ATAB2 CONTAINS ALL OPCODES.
;
ATAB2:
DB 'NOP '
DB 'LXI '
DB 'STAX'
DB 'LDAX'
DB 'SHLD'
DB 'LHLD'
DB 'INX '
DB 'DCX '
DB 'INR '
DB 'DCR '
DB 'RLC '
DB 'RRC '
DB 'RAL '
DB 'RAR '
DB 'DAD '
DB 'DAA '
DB 'CMA '
DB 'STA '
DB 'LDA '
DB 'STC '
DB 'CMC '
DB 'MOV '
DB 'ADD '
DB 'ADC '
DB 'SUB '
DB 'SBB '
DB 'ANA '
DB 'XRA '
DB 'ORA '
DB 'CMP '
DB 'MVI '
DB 'ADI '
DB 'ACI '
DB 'SUI '
DB 'SBI '
DB 'ANI '
DB 'XRI '
DB 'ORI '
DB 'CPI '
DB 'RET '
DB 'JMP '
DB 'CALL'
DB 'RNZ '
DB 'JNZ '
DB 'CNZ '
DB 'RZ '
DB 'JZ '
DB 'CZ '
DB 'RNC '
DB 'JNC '
DB 'CNC '
DB 'RC '
DB 'JC '
DB 'CC '
DB 'RPO '
DB 'JPO '
DB 'CPO '
DB 'RPE '
DB 'JPE '
DB 'CPE '
DB 'RP '
DB 'JP '
DB 'CP '
DB 'RM '
DB 'JM '
DB 'CM '
DB 'POP '
DB 'PUSH'
DB 'XTHL'
DB 'PCHL'
DB 'XCHG'
DB 'SPHL'
DB 'OUT '
DB 'IN '
DB 'DI '
DB 'EI '
DB 'HLT '
DB 'RST0'
DB 'RST1'
DB 'RST2'
DB 'RST3'
DB 'RST4'
DB 'RST5'
DB 'RST6'
DB 'RST7'
DB 'RIM '
DB 'SIM '
AT2E: DB 0FFH,0FFH,0FFH,0FFH
DB '--- '
;
;**** ATAB3 CONTAINS ALL POSSIBLE OPERANDS.
;
ATAB3:
DB ' '
DB 'B '
DB 'C '
DB 'D '
DB 'E '
DB 'H '
DB 'L '
DB 'M '
DB 'A '
DB 'SP '
DB 'PSW'
DB 'B,B'
DB 'B,C'
DB 'B,D'
DB 'B,E'
DB 'B,H'
DB 'B,L'
DB 'B,M'
DB 'B,A'
DB 'C,B'
DB 'C,C'
DB 'C,D'
DB 'C,E'
DB 'C,H'
DB 'C,L'
DB 'C,M'
DB 'C,A'
DB 'D,B'
DB 'D,C'
DB 'D,D'
DB 'D,E'
DB 'D,H'
DB 'D,L'
DB 'D,M'
DB 'D,A'
DB 'E,B'
DB 'E,C'
DB 'E,D'
DB 'E,E'
DB 'E,H'
DB 'E,L'
DB 'E,M'
DB 'E,A'
DB 'H,B'
DB 'H,C'
DB 'H,D'
DB 'H,E'
DB 'H,H'
DB 'H,L'
DB 'H,M'
DB 'H,A'
DB 'L,B'
DB 'L,C'
DB 'L,D'
DB 'L,E'
DB 'L,H'
DB 'L,L'
DB 'L,M'
DB 'L,A'
DB 'M,B'
DB 'M,C'
DB 'M,D'
DB 'M,E'
DB 'M,H'
DB 'M,L'
DB 'M,M'
DB 'M,A'
DB 'A,B'
DB 'A,C'
DB 'A,D'
DB 'A,E'
DB 'A,H'
DB 'A,L'
DB 'A,M'
DB 'A,A'
AT3E: DB 0FFH,0FFH,0FFH
;
; LOAD HEX OBJECT TAPE.
;
; LOAD A HEX-BINARY TAPE AS PRODUCED BY THE 'P'
; COMMAND.
; MAY CONTAIN AN OFFSET VALUE, ALLOWING THE DATA TO
; BE LOADED INTO A DIFFERENT LOCATION TO THAT SPECIFIED
; BY THE LOAD ADDRESS.
;
;
SPORT EQU 083H
DPORT EQU 083H
SPKT EQU 080H
;
ORG ROM+0F40H
;
LOADF:
CALL PUWB ;GET THE OFFSET, IF ANY.
JNC LD4F
CPI CR ;ERROR MAY ONLY BE <CR>
JNZ ILLEG
LD4F:
CALL CRLF ;NEW LINE PLEASE.
PUSH H ;SAVE BIAS ADR
LD5F:
POP H ;GET BIAS
PUSH H ;AND RESTORE
CALL RIXF ;GET INPUT
MVI B,':' ;WAIT FOR ':'
SUB B
JNZ LD5F ;TRY AGAIN
MOV D,A ;CLEAR CKSUM
CALL BYTEF ;GET LENGTH
JZ LD7F ;ZERO MEANS ALL DONE
MOV E,A ;SAVE LENGTH
CALL BYTEF
PUSH PSW ;SAVE HI ADR
CALL BYTEF
POP B ;FETCH MSBYTE
MOV C,A ;BC NOW HAS ADR
PUSH B ;SAVE IT
XTHL ;INTO HL
SHLD BLKAD ;SAVE BLOCK ADR
XTHL ;IN CASE OF ERROR
POP B
DAD B ;RESTORE AND ADD BIAS
CALL BYTEF ;RECORD TYPE INPUT
LD6F:
CALL BYTEF ;GET DATA BYTES
CALL STORE ;STORE
INX H
DCR E
JNZ LD6F ;GO ON.
CALL BYTEF ;GET CKSUM
JZ LD5F
LDERRF:
LXI H,M6 ;CKSUM ERROR
CALL MSG
LHLD BLKAD ;ADR OF THIS BLOCK IS
JMP RXAR ;NOW GIVEN
LD7F:
CALL BYTEF ;MSB OF XEQAD
MOV H,A
CALL BYTEF
MOV L,A
ORA H
JZ NEXT ;MONITOR IF ADR=0
PCHL ;OTHERWISE EXECUTE
;
RIXF:
CALL RIF
JC ILLEG ;ON ERROR, PRINT '??'
ANI 7FH ;REMOVE PARITY
RET
;
; ROUTINE RIF
; GETS A CHARACTER FROM THE FAST READER INPUT
; I.E. IT STARTS THE READER, AND EXPECTS QUICK REPLY.
;
;
RIF:
PUSH B ;SAVE BC
PUSH D ;AND DE
RIF05:
MVI C,SPKT ;PRESET CURRENT STATUS
LXI D,0 ;TIMEOUT COUNT.
RIF10:
IN SPORT ;GET STATUS.
ANI SPKT ;LOOK AT SPROCKET ONLY.
MOV B,A ;SAVE IT.
MOV A,C ;OLD STATUS
CMA ;IS INVERTED
ANA B ;SO THAT + EDGE IS FOUND.
MOV C,B ;SAVE CURRENT STATUS.
JNZ RIF15 ;NON-ZERO=GOT IT.
DCX D ;DROP T/O COUNT
MOV A,D ;SEE IF
ORA E ;COUNT IS
JNZ RIF10 ;ZERO YET.
STC
POP D
POP B
RET
RIF15:
IN DPORT ;AND GET DATA.
ORA A ;CLEAR CARRY ONLY.
POP D
POP B ;RESTORE BC
RET ;SIMPLY RETURN
;
BYTEF:
PUSH B ;SAVE BC
CALL RIXF ;READ ASCII
CALL CNVBN ;CONVERT TO HEX
JC LDERR ;ERROR DETECTOR.
RLC ;SHIFT LEFT 4 BITS
RLC
RLC
RLC
MOV B,A ;SAVE THEM A WHILE
CALL RIXF ;GET SECOND BYTE
CALL CNVBN ;CONVERT TO HEX
JC LDERR ;ERROR DETECTOR
ORA B ;OR IN THE SAVED NYBBLE
MOV C,A ;HOLD BYTE A WHILE.
ADD D ;ADD TO CKSUM
MOV D,A ;UPDATE CKSUM
MOV A,C ;RESTORE BYTE
POP B ;RESTORE BC
RET
;
;
; END OF ROM ROUTINES.
;
;
ENDROM EQU $
;
;
; SYSTEM RAM AREA DEFINITION.
;
;
ORG RAM
;
; STACK GOES IN HERE, PACKING DOWN FROM
; STORAGE AREA.
;
ORG REGS
;
; MONITOR REG. SAVE AREA.
;
SVPC:
SVPCL: DS 1 ;SAVED PC LOW
SVPCH: DS 1 ;SAVED PC HI
SVSP:
SVSPL: DS 1 ;SAVED SP LOW
SVSPH: DS 1 ;SAVED SP HI
SVHL:
SVL: DS 1 ;SAVED L
SVH: DS 1 ;SAVED H
SVE: DS 1 ;SAVED E
SVD: DS 1 ;SAVED D
SVC: DS 1 ;SAVED C
SVB: DS 1 ;SAVED B
SVF: DS 1 ;SAVED PSB, FLAGS
SVA: DS 1 ;SAVED ACC
;
; SPECIALS USED BY MONITOR
;
BUFF:
TMPA:
GOGO: DS 3
DSA: DS 2 ;START OF ROM DATA
OPCODE:
DFA: DS 2 ;END OF ROM DATA
MEMADR:
ROMADR: DS 2 ;PROM ADDRESS POINTER.
ECHO: DS 1 ;CHARACTER ECHO FLAG 0=NO ECHO
ADR: DS 2 ;EXAMINE/MODIFY ADR
XEQAD: DS 2 ;'X' EXECUTION ADR
BLKAD: DS 2 ;'L' BLOCK ADR
BPADD: DS 2 ;BREAKPOINT SAVE ADDRESS
BPDAT: DS 6 ;BREAKPOINT SAVE DATA
USERA: DS 2 ;USER FUNCTION VECTOR ADDRESS
;
; USER VECTORS RST3-RST7
;
RST3: DS 2
RST4: DS 2
RST5: DS 2
RST6: DS 2
RST7: DS 2
;
;
END