mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 08:24:18 +00:00
1532 lines
36 KiB
NASM
1532 lines
36 KiB
NASM
;
|
|
;CP/M MACRO ASSEM 2.0 #001 MOSS 2.2 MONITOR
|
|
;
|
|
TITLE 'MOSS 2.2 MONITOR'
|
|
PAGE 68
|
|
MACLIB Z80
|
|
;
|
|
.8080
|
|
;
|
|
; MOSS MONITOR (VERSION 2.2)
|
|
;
|
|
; 20 JUNE 1980
|
|
; ALL RIGHTS RESERVED BY ROBERT B. MASON
|
|
;
|
|
; OCR PDF Documents 09-20-2014 by Larry Kraemer
|
|
; Modify Z80.LIB to add needed Macro's by Garry Kraemer
|
|
; Debugging & Corrections by Garry Kraemer - Senior Software Engineer
|
|
;
|
|
MOSS ORG 0F000H
|
|
ROM EQU 0F000H ;ROM START ADDRESS
|
|
WSVEC EQU 0 ;VECTOR FOR WARM RESTART
|
|
NBKPTS EQU 2 ;NUMBER OF BREAKPOINTS
|
|
CTRLS EQU 13H ;ASCII DC3
|
|
CR EQU 0DH ;ASCII CARRIAGE RETURN
|
|
LF EQU 0AH ;ASCII LINE FEED
|
|
FMFD EQU 0CH ;ASCII FORM FEED
|
|
BELL EQU 7 ;ASCII CNTRL CHAR TO RING THE BELL
|
|
IOBYTE EQU 3 ;ADDRESS OF I/O CONTROL BYTE
|
|
SDATA EQU 20H ;SERIAL DATA PORT BASE ADDRESS
|
|
SINTEN EQU SDATA+1 ;SERIAL INTERRUPT ENABLE REGISTER
|
|
SIDENT EQU SDATA+2 ;SERIAL INTERRUPT IDENTIFICATION REGIS
|
|
SLCTRL EQU SDATA+3 ;SERIAL LINE CONTROL REGISTER
|
|
SMDMCT EQU SDATA+4 ;SERIAL MODEM CONTROL REGISTER
|
|
SLSTAT EQU SDATA+5 ;SERIAL LINE STATUS REGISTER
|
|
SMDMST EQU SDATA+6 ;SERIAL MODEM STATUS REGISTER
|
|
;
|
|
;
|
|
SPSV EQU 6 ;STACK POINTER SAVE LOCATION
|
|
;
|
|
;
|
|
; REGISTER STORAGE DISPLACEMENTS FROM
|
|
; NORMAL SYSTEM STACK LOCATION.
|
|
;
|
|
ALOC EQU 15H
|
|
BLOC EQU 13H
|
|
CLOC EQU 12H
|
|
DLOC EQU 11H
|
|
ELOC EQU 10H
|
|
FLOC EQU 14H
|
|
HLOC EQU 31H
|
|
LLOC EQU 30H
|
|
PLOC EQU 34H
|
|
SLOC EQU 17H
|
|
TLOC EQU 35H
|
|
TLOCX EQU 25H
|
|
LLOCX EQU 20H
|
|
APLOC EQU 9
|
|
BPLOC EQU 11
|
|
CPLOC EQU 10
|
|
DPLOC EQU 13
|
|
EPLOC EQU 12
|
|
FPLOC EQU 8
|
|
HPLOC EQU 15
|
|
LPLOC EQU 14
|
|
XLOC EQU 7
|
|
YLOC EQU 5
|
|
RLOC EQU 2
|
|
ILOC EQU 3
|
|
;
|
|
; JUMP TARGETS FOR BASIC INPUT/OUTPUT
|
|
;
|
|
CBOOT: JMP INIT ;COLD START
|
|
CONIN: JMP CI ;CONS0LE INPUT
|
|
READER: JMP RI ;READER INPUT
|
|
CONOUT: JMP CO ;CONSOLE OUTPUT
|
|
PUNCH: JMP PO ;PUNCH OUTPUT
|
|
LIST: JMP LO ;LIST OUTPUT
|
|
CONST: JMP CSTS ;CONSOLE STATUS
|
|
JMP IOCHK ;PUT IOBYTE INTO (A)
|
|
JMP IOSET ;(C) HAS A NEW IOBYTE
|
|
JMP MEMCK ;MEMORY LIMIT CHECK
|
|
JMP RTS ;IODEF- DEFINE USER I/O ENTRY POINTS
|
|
JMP RTS ;SPCL- I/O CONTROL
|
|
JMP REST ;BREAKPOINT ENTRY POINT
|
|
;
|
|
; TBL CONTAINS THE ADDRESSES OF THE ACTION ROUTINES
|
|
; THE EXECUTIVE USES IT TO LOOK UP THE DESIRED ADDRESS.
|
|
TBL: DW ASGN
|
|
DW QPRT
|
|
DW QPRT
|
|
DW DISP
|
|
DW EOF
|
|
DW FILL
|
|
DW GOTO
|
|
DW HEXN
|
|
DW INPT
|
|
DW QPRT
|
|
DW QPRT
|
|
DW LEADER
|
|
DW MOVE
|
|
DW QPRT
|
|
DW OUPT
|
|
DW QPRT
|
|
DW QUERY
|
|
DW READ
|
|
DW SUBS
|
|
DW MTEST
|
|
DW QPRT
|
|
DW COMP
|
|
DW WRITE
|
|
DW XMNE
|
|
DW I8250
|
|
DW BYE
|
|
;
|
|
; THE COLD INITIALIZATION CODE
|
|
;
|
|
INIT: DI ;DISABLE INTERRUPTS
|
|
LXI SP,3FH ;USE STACK TO INITIALIZE RESTARTS
|
|
LXI H,JMP*256 ; WITH RESTART ERROR VECTORS
|
|
LXI D,RSTER
|
|
MVI B,16 ;16 TIMES (64 BYTES)
|
|
INIT1: PUSH D
|
|
PUSH H
|
|
DJNZ INIT1
|
|
;
|
|
LXI SP,FAKE-2 ;SET UP TEMPORARY STACK
|
|
MVI A,0 ;SKIP THE NEXT INST
|
|
ORG $-1 ;SAVE A BYTE HERE
|
|
;
|
|
; MEMSIZ CALCULATES THE TOP OF CONTIGUOUS RAM. IT SEARCHES
|
|
; FROM THE BOTTOM UP UNTIL A NON-RAM LOCATION IS
|
|
; FOUND. IT THEN TAKES OFF FOR MONITOR WORK SPACE
|
|
; NEEDS AND RETURNS THE VALUE IN (H,L).
|
|
MEMSIZ: PUSH B ;MOITOR START LOCATION
|
|
LXI B,ROM
|
|
LXI H,-1 ;START OF MEMORY ADDRESS SPACE
|
|
MEMSZ1: INR H
|
|
MOV A,M
|
|
CMA
|
|
MOV M,A
|
|
CMP M
|
|
CMA
|
|
MOV M,A
|
|
JRNZ MEMSZ2
|
|
;
|
|
MOV A,H ;SEE IF ON MONITOR BORDER
|
|
CMP B
|
|
JRNZ MEMSZ1
|
|
;
|
|
MEMSZ2: DCR H ;TAKE OFF WORKSPACE
|
|
LXI B,EXIT-ENDX-3*NBKPTS+1
|
|
DAD B
|
|
POP B ;(B,C) IS UNPREDICTABLE DURING INIT
|
|
RET
|
|
;
|
|
; ROUTINE MEMCHK FINDS THE CURRENT TOP OF CONTIGUOUS MEMORY
|
|
; (LESS THE MONITOR WORKSPACE) AND RETURNS THE VALUE.
|
|
;
|
|
MEMCK: PUSH H ;SAVE (H,L)
|
|
CALL MEMSIZ ;GET THE RAM SIZE
|
|
MOV A,L
|
|
SUI 60 ;TAKE OFF WORK SPACE
|
|
JRNC MEMCK0
|
|
;
|
|
DCR H
|
|
MEMCK0: MOV B,H
|
|
POP H
|
|
RET
|
|
;
|
|
FAKE: DW FAKE+2
|
|
SPHL
|
|
LXI D,EXIT
|
|
XCHG
|
|
LXI B,ENDX-EXIT
|
|
LDIR
|
|
;
|
|
LXI B,3*NBKPTS
|
|
PUSH D
|
|
POP H
|
|
DCX H
|
|
LDIR
|
|
;
|
|
LXI H,-24
|
|
DAD SP
|
|
PUSH H
|
|
INX H ;ADJUST USER STACK LOCATION
|
|
INX H
|
|
SHLD SPSV ;SAVE THE STACK INITIAL VALUE
|
|
MVI D,10 ;INITIALIZE REGISTER STORAGE AREA
|
|
INIT2: PUSH B
|
|
DCR D ;LOOP CONTROL
|
|
JRNZ INIT2
|
|
;
|
|
; INSERT I/O INIT CODE HERE
|
|
CALL RTS
|
|
CALL I8250 ;INITIALIZE THE 8250
|
|
CALL RTS
|
|
LXI H,LOGMSG ;LOG ONTO THE SYSTEM
|
|
CALL PRTWD
|
|
JMPR WINIT ;GO TO MONITOR EXECUTIVE
|
|
;
|
|
; ROUTINE EXF READS ONE PARAMETER. IT EXPECTS THE FIRST
|
|
; CHARACTER OF THE PARAMETER TO BE IN THE A REGISTER
|
|
; ON ENTRY.
|
|
EXF: MVI B,1 ;SET UP FOR ONE PARAMETER
|
|
LXI H,0
|
|
JMPR EX1 ;FIRST CHARACTER IN A ALREADY
|
|
;
|
|
; ROUTINE EXPR READS PARAMETERS FROM THE CONSOLE
|
|
; AND DEVELOPS A 16 BIT HEXADECIMAL FOR EACH ONE.
|
|
; THE NUMBER OF PARAMETERS WANTED IS IN THE B REG
|
|
; ON ENTRY. A CARRIAGE RETURN WILL TERMINATE THE
|
|
; ENTRY SEQUENCE. A BLANK OR A COMMA WILL END THE
|
|
; CURRENT PARAMETER ENTRY. EACH PARAMETER ONLY
|
|
; TAKES THE LAST 4 DIGITS TYPED IN; ANY EXCESS IS
|
|
; DISCARDED. A NON-HEX DIGIT WILL TERMINATE THE
|
|
; ENTRY SEQUENCE AND CAUSE A WARM BOOT OF THE MON.
|
|
;
|
|
AS3: DJNZ AS2 ;PART OF THE ASSIGN CODE
|
|
;
|
|
EX3: JRNZ QPRT ;NON-ZERO IS ERROR
|
|
;
|
|
EXPR1: DCR B ;MORE PARAMETERS?
|
|
RZ ;NO, RETURN
|
|
EXPR: LXI H,0 ;INITIALIZE PARAMETER
|
|
EX0: CALL ECHO ;GET NEXT NUMBER
|
|
EX1: MOV C,A ;SAVE CHAR FOR LATER USE
|
|
CALL NIBBLE
|
|
JRC EX2 ;NOT A NUMBER, JUMP
|
|
;
|
|
DAD H ;MULTIPLY BY 16
|
|
DAD H
|
|
DAD H
|
|
DAD H
|
|
ORA L ;ADD ON NEW DIGIT
|
|
MOV L,A
|
|
JMPR EX0 ;GO GET NEXT DIGIT
|
|
;
|
|
EX2: XTHL ;PUT UNDER RETURN ADDRESS ON STACK
|
|
PUSH H ;RESTORE RETURN ADDRESS
|
|
MOV A,C ;REGET THE LAST CHARACTER
|
|
CALL P2C ;TEST FOR DELIMITER
|
|
JRNC EX3 ;JUMP IF NOT CARRIAGE RETURN
|
|
;
|
|
DJNZ QPRT ;CARRET WITH MORE PARAM MEANS ERROR
|
|
;
|
|
RET
|
|
;
|
|
; MAIN ACTION ROUTINES
|
|
;
|
|
; LOGICAL ASSIGNMENT OF PERIPHERALS
|
|
;
|
|
;THIS ROUTINE CONTROLS THE ASSIGNMENT OF PHYSICAL
|
|
;PERIPHERALS TO THE FOUR LOGICAL DEVICE TYPES. IT
|
|
;ALTERS IOBYTE (MEMORY LOCATION 0003) TO MATCH THE
|
|
;CURRENT ASSIGNMENT. THE FOUR LOGICAL DEVICES ARE
|
|
;CONSOLE, READER LIST, AND PUNCH. IN ALL CASES,
|
|
;THE TTY DEVICE IS SET UP AS THE DEFAULT DEVICE.
|
|
;
|
|
ASGN: CALL ECHO ;GET THE LOGICAL DEVICE DESIRED
|
|
LXI H,ALT ;START OF CONVERSION TABLE
|
|
LXI D,APT-ALT ;DISTANCE BETWEEN LOGICAL CHOICE
|
|
MVI B,4 ;NUMBER OF LOGICAL CHOICES
|
|
AS0: CMP M ;IS THS ONE IT?
|
|
JRZ AS1 ;YES, JUMP
|
|
;
|
|
DAD D ;NO, GO TO NEXT LOGICAL ENTRY
|
|
DJNZ AS0
|
|
;
|
|
QPRT: LXI H,QMSG ;GET ADDRESS OF QUESTION MARK MSG
|
|
CALL PRTWA ;PRNT IT
|
|
; THE WARM START CODE
|
|
WINIT: LHLD SPSV ;RESET THE STACK
|
|
SPHL
|
|
WINITA: LXI H,WINIT ;RESET RETURN AND WARM START VECTOR
|
|
PUSH H
|
|
SHLD WSVEC+1
|
|
MVI A,0C3H
|
|
STA WSVEC
|
|
CALL CRLF ;START A NEW LINE
|
|
CALL DECHO ;GET THE COMMAND
|
|
SUI 'A' ;GET RID OF ASCII ZONE
|
|
JRC QPRT ;BAD COMMAND
|
|
;
|
|
CPI 'Z'-'A'+1 ;CHECK UPPER LIMIT
|
|
JRNC QPRT ;BAD COM AND
|
|
;
|
|
ADD A ;DOUBLE IT FOR TABLE OFFSET
|
|
MOV E,A ;SET UP FOR DOUBLE ADD
|
|
MVI D,0
|
|
MVI B,2 ;SET UP FOR TWO PARAMETERS
|
|
LXI H,TBL ;GET ACTION ROUTINE ADDRESS
|
|
DAD D
|
|
MOV A,M ;LOAD H,L INDIRECT
|
|
INX H
|
|
MOV H,M
|
|
MOV L,A
|
|
PCHL ;GO TO ACTION ROUTINE
|
|
;
|
|
; FILL ACTION ROUTINE
|
|
;
|
|
;THIS ROUTINE FILLS A BLOCK OF MEMORY WITH A USER-
|
|
;DETERMINED CONSTANT. IT EXPECTS THREE PARAMETERS
|
|
;TO BE ENTERED IN THE FOLLOWING ORDER:
|
|
;
|
|
;START ADDRESS
|
|
;FINISH ADDRESS
|
|
;FILL VALUE
|
|
;
|
|
FILL: CALL EXPR3 ;GET THREE PARAMETERS
|
|
FIO: MOV M,C ;PUT DOWN THE FILL VALUE
|
|
CALL HILO ;INCREMENT AND CHECK THE POINTER
|
|
JRNC FIO ;NOT DONE YET, JUMP
|
|
POP D ;RESTORE STACK POINTER IN CASE
|
|
JMPR WINIT ; STACK WAS OVERWRITTEN
|
|
;
|
|
AS1: MOV D,B ;SAVE THE COUNTER RESIDUE
|
|
MVI B,4 ;LOOP CONTROL
|
|
CALL DECHO ;GET THE NEW ASSIGNMENT
|
|
AS2: INX H ;INCREMENT POINTER
|
|
CMP M ;SEE IF THIS IS IT
|
|
JRNZ AS3
|
|
;
|
|
MOV L,B ;SAVE THE RESIDUE TO FORM ASGT
|
|
DCR L ;ADJUST VALUE
|
|
MOV B,D ;REGET THE LOGICAL RESIDUE
|
|
MVI H,3 ;SET UP THE IOBYTE MASK
|
|
DCR B ;ADJUST THIS ONE ALSO
|
|
JRZ AS5 ;NO SHFT NEEDED
|
|
;
|
|
AS4: DAD H ;SHIFT THE MASKS INTO POSITION
|
|
DAD H
|
|
DJNZ AS4 ;NOT DONE YET, JUMP
|
|
;
|
|
AS5: LDA IOBYTE
|
|
ORA H ;MASK THE DESIRED ASSIGNMENT IN
|
|
XRA H ;LOGICAL ASGT BITS NOW OFF
|
|
ORA L ;PUT IN NEW VALUE
|
|
MOV C,A
|
|
IOSET: MOV A,C
|
|
STA IOBYTE ;SAVE NEW ASSIGNMENTS
|
|
RET
|
|
IOCHK: LDA IOBYTE
|
|
RET
|
|
;
|
|
ALT: DB 'L' ;LOGICAL LIST DEVICE TABLE
|
|
DB '2' ;USER DEVICE #2
|
|
DB '1' ;USER DEVICE #1
|
|
DB 'L' ;LIST TO HIGH SPEED PRINTER
|
|
DB 'T' ;LIST TO TTY
|
|
APT: DB 'P' ;LOGICAL PUNCH DEVICE TABLE
|
|
DB '2' ;USER DEVICE #2
|
|
DB '1' ;USER DEVICE #1
|
|
DB 'P' ;PUNCH TO HIGH SPEED PUNCH
|
|
DB 'T' ;PUNCH TO TTY
|
|
ART: DB 'R' ;LOGICAL READER DEVICE TABLE
|
|
DB '2' ;USER DEVICE #2
|
|
DB '1' ;USER DEVICE #1
|
|
DB 'P' ;READER TO HIGH SPEED READER
|
|
DB 'T' ;READER TO TTY
|
|
ACT: DB 'C' ;LOGICAL CONSOLE DEVICE TABLE
|
|
DB '1' ;USER DEVICE #1
|
|
DB 'B' ;CONSOLE TO BATCH (PRINTER OR PTR)
|
|
DB 'C' ;CONSOLE TO CRT
|
|
DB 'T' ;CONSOLE TO TTY
|
|
;
|
|
; THE BYE ROUTINE IS USED TO PREVENT UNAUTHORIZED USAGE
|
|
; OF THE SYSTEM. THE SYSTEM LOCKS UP AND WILL NOT
|
|
; RESPOND TO ANYTHING OTHER THAN TWO ASCII BELL
|
|
; CHARACTERS. WHEN IT SEES THEM CONSECUTIVELY
|
|
; CONTROL IS RETURNED TO THE MONITOR WITHOUT ALTERING
|
|
; ANYTHING.
|
|
;
|
|
BYE: MVI B,2 ;SET UP FOR TWO CHARACTERS
|
|
BYE1: CALL CONI ;GO READ THE CONSOLE
|
|
CPI BELL ;SEE IF AN ASCII BELL
|
|
JRNZ BYE ;NO, START OVER AGAIN
|
|
;
|
|
CALL ECH1 ;ECHO THE BELL
|
|
DJNZ BYE1 ;NOT YET, GET NEXT ONE
|
|
;
|
|
RET ;RETURN TO MONITOR
|
|
;
|
|
; COMPARE ROUTINE
|
|
;
|
|
;THIS ROUTINE COMPARES TWO BLOCKS OF MEMORY AGAINST EACH
|
|
; OTHER. IF A DIFFERENCE IN THE RELATIVE ADDRESS
|
|
; CONTENTS IS DETECTED THE ADDRESS OF THE FIRST
|
|
; BLOCK IS DISPLAYED ALONG WITH ITS CONTENTS AND
|
|
; THE CONTENTS OF THE OTHER BLOCK'S SAME RELATIVE
|
|
; ADDRESS.
|
|
COMP: CALL EXPR3 ;GO GET THREE PARAMETERS
|
|
CMPA: LDAX B ;GET SOURCE 2 DATA
|
|
PUSH B ;SAVE SOURCE 2 POINTER
|
|
MOV B,M ;READ SOURCE 1 DATA
|
|
CMP B ;COMPARE DATA
|
|
JRZ CMPB ;JUMP IF OK
|
|
;
|
|
PUSH PSW ;SAVE SOURCE 2 DATA
|
|
CALL LADRB ;WRITE THE ADDRESS
|
|
MOV A,B ;GET SOURCE 1 DATA
|
|
CALL DASH1 ;FORMAT
|
|
POP PSW ;REGET SOURCE 2 DATA
|
|
CALL HEX1 ;OUTPUT IT
|
|
CMPB: POP B
|
|
CALL HILOXB ;INCREMENT SOURCE I POINTER AND SEE IF
|
|
JMPR CMPA ;JUMP IF NOT DONE YET
|
|
;
|
|
;
|
|
; DISPLAY ACTION ROUTINE
|
|
; THIS ROUTINE DISPLAYS A BLOCK OF MEMORY ON THE
|
|
; CURRENT CONSOLE DEVICE (CONSOLE DUMP). THE USER
|
|
; MUST SPECIFY THE START AND FINISH ADDRESSES.
|
|
; THE DISPLAY IS ORGANIZED TO DISPLAY UP TO 16 BYTES
|
|
; PER DISPLAY LTNE WITH ALL COLUMNS ALIGNED SO
|
|
; EACH COLUMN HAS THE SAME LAST HEX DIGIT IN ITS ADDRESS
|
|
;
|
|
DISP: CALL EXLF ;GO GET BLOCK LIMITS
|
|
DIS1: CALL LADRB ;DISPLAY THE START ADDRESS
|
|
MOV A,L ;SEE IF ON 16 BYTE BOUNDARY
|
|
CALL TRPLSP ;SKIP OVER TO RIGHT COLUMN
|
|
PUSH H ;SAVE (H,L)
|
|
DIS2: MOV A,M ;GET THE CONTENTS
|
|
CALL HEX1 ;OUTPUT IT
|
|
CALL HILO ;INCREMENT CHECK POINTER
|
|
JRC DIS7 ;DONE IF CARRY SET
|
|
CALL BLK ;MAKE COLUMNS
|
|
MOV A,L ;READY FOR NEW LINE?
|
|
ANI 0FH
|
|
JRNZ DIS2
|
|
;
|
|
DIS3: POP H ;REGET LINE START ADDRESS
|
|
MOV A,L ;SKIP OVER TO RIGHT SPACE
|
|
ANI 0FH
|
|
CALL TRPL2
|
|
DIS4: MOV A,M ;GET MEMORY VALUE
|
|
ANI 7FH ;STRIP OFF PARITY BIT
|
|
MOV C,A ;SET UP FOR OUTPUT
|
|
CPI ' ' ;SEE IF PRINTABLE IN ASCII
|
|
JRC DIS5 ;JUMP IF' SO
|
|
;
|
|
CPI 7EH
|
|
JRC DIS6
|
|
;
|
|
DIS5: MVI C,'.' ;ELSE, PRINT A DOT
|
|
DIS6: CALL CONOUT
|
|
CALL HILOX ;INCREMENT (H,L) AND SEE IF DONE
|
|
MOV A,L ;NOT DONE, READY FOR NEW LINE?
|
|
ANI 0FH
|
|
JRNZ DIS4 ;JUMP IF NOT
|
|
;
|
|
JMPR DIS1 ;DO THE NEXT LINE
|
|
;
|
|
DIS7: SUB E ;SKIP OVER TO START ASCII PRINTOUT
|
|
CALL TRPLSP
|
|
JMPR DIS3 ;GO PRINT THE ASCII
|
|
;
|
|
;
|
|
TRPLSP: ANI 0FH ;ISOLATE THE LOW FOUR BITS
|
|
MOV B,A ;PREPARE TO SPACE OVER TO RIGHT COLUMN
|
|
ADD A ;TRIPLE THE COUNT
|
|
ADD B
|
|
TRPL2: MOV B,A ;PUT BACK INTO B
|
|
INR B ;ADJUST COUNTER
|
|
TRPL1: CALL BLK ;DO THE SPACING
|
|
DJNZ TRPL1 ;NO, DO ANOTHER COLUMN
|
|
;
|
|
RET
|
|
;
|
|
; GO TO ACTION ROUTINE
|
|
;
|
|
; GOTO COMMAND TRANSFERS CONTROL TO A SPECIFIED ADDRESS.
|
|
; IT ALLOWS THE SELECTIVE SETTING OF UP TO TWO BREAKPOINTS
|
|
; AS WELL AS ALLOWING ANY CONSOLE INPUT TO BREAKPOINT
|
|
; THE RUN, AS LONG AS INTERRUPT 1 IS ACTIVE.
|
|
;
|
|
GOTO: CALL PCHK ;SEE IF OLD ADDRESS WANTED
|
|
JRC GO3 ; YES, JUMP
|
|
JRZ GO0 ; YES, BUT SET SOME BREAKPOINTS
|
|
CALL EXF ;GET NEW GOTO ADDRESS
|
|
POP D
|
|
LXI H,PLOC ;PUT ADDRESS IN PC LOCATION
|
|
DAD SP
|
|
MOV M,D ;LOW BYTE
|
|
DCX H
|
|
MOV M,E ;HIGH BYTE
|
|
MOV A,C
|
|
CPI CR ;SEE IF A CR WAS LAST ENTERED
|
|
JRZ GO3
|
|
;
|
|
GO0: MVI B,NBKPTS
|
|
LXI H,TLOC ;POINT TO TRAP STORAGE
|
|
DAD SP
|
|
GO1: PUSH B ;SAVE NUMBER OF BREAKPOINTS
|
|
PUSH H ;SAVE STORAGE POINTER
|
|
MVI B,2 ;SET UP TO GET A TRAP ADDRESS
|
|
CALL EXPR1 ;GET A TRAP ADDRESS
|
|
POP D ;GET THE TRAP ADDRESS INTO (D,E)
|
|
POP H ;REGET THE STORAGE ADDRESS
|
|
MOV A,D ;INSURE THE TRAP ADDRESS ISN'T ZERO
|
|
ORA E
|
|
JRZ GO2 ;JUMP IF SO
|
|
;
|
|
MOV M,E ;SAVE THE BREAKPOINT ADDRESS
|
|
INX H
|
|
MOV M,D
|
|
INX H
|
|
LDAX D ;SAVE THE INSTRUCTION FROM THE BP ADDR
|
|
MOV M,A
|
|
INX H
|
|
MVI A,RST OR 8 ;INSERT THE BREAKPOINT
|
|
STAX D
|
|
GO2: MOV A,C ;REGET THE DELIMITER TO SEE
|
|
CPI CR ; IF WE ARE DONE SETTING BREAKPOINTS
|
|
POP B ; UNLOAD THE STACK FIRST
|
|
JRZ GO3 ;YES, JUMP
|
|
;
|
|
DJNZ GO1 ;JUMP IF NOT AT BP LIMIT
|
|
;
|
|
GO3: CALL CRLF
|
|
POP H ;GET RID OF STACK JUNK
|
|
LXI H,RS9
|
|
PUSH H
|
|
LXI H,REST
|
|
SHLD 9 ;SET BREAKPOINT JUMP VECTOR ADDRESS
|
|
LXI H,24 ;FIND REGISTER SET ROUTINE ADDRESS
|
|
DAD SP
|
|
POP D ;ADJUST THE STACK
|
|
PCHL ;GO TO THE DESIRED PLACE
|
|
;
|
|
; GENERAL PURPOSE INPUT/OUTPUT ROUTINES
|
|
;
|
|
;THESE ROUTINES ALLOW BYTE BY BYTE INPUT OR OUTPUT FROM
|
|
; THE CURRENT CONSOLE DEVICE. THEY ARE INVOKED BY
|
|
; THE MONITOR "I" OR "O" COMMAND.
|
|
INPT: CALL EXPR1 ;GET INPUT PORT NUMBER
|
|
POP B ;GET PORT # INTO C REGISTER
|
|
INP E ;READ VALUE INTO E REGISTER
|
|
;
|
|
JMPR BITS2 ;GO DO A BINARY PRINT OF THE VALUE
|
|
;
|
|
OUPT: CALL EXPR ;GET THE ADDRESS AND DATA FOR OUTPUT
|
|
POP D ;DATA VALUE INTO E
|
|
POP B ;PORT INTO C
|
|
OUTP E ;DO THE OUTPUT
|
|
;
|
|
RET
|
|
;
|
|
; MOVE ROUTINE
|
|
; THIS ROUTINE EXPECTS THREE PARAMETERS, ENTERED IN THE
|
|
; SOURCE FIRST BYTE ADDRESS
|
|
; SOURCE LAST BYTE ADDRESS
|
|
; DESTINATION FIRST BYTE ADDRESS
|
|
;
|
|
MOVE: CALL EXPR3 ;GET THREE PARAMETERS
|
|
MOV1: MOV A,M ;GET NEXT BYTE
|
|
STAX B ;MOVE IT
|
|
CALL HILOXB ;GO INCREMENT CHECK SOURCE POINTER
|
|
JMPR MOV1 ;NOT THERE YET, GO DO IT AGAIN
|
|
;
|
|
;
|
|
; SUBSTITUTE ACTION ROUTINE
|
|
;
|
|
; THIS ROUTINE ALLOWS THE USER TO INSPECT ANY MEMORY LOCATION
|
|
; AND ALTER THE CONTENTS TF DESIRED AND IF THE ADDRESS
|
|
; IS IN RAM. THE CONTENtS MAY BE LEFT UNALTERED
|
|
; BY ENTERING A SPACE, COMMA OR A CARRIAGE RETURN. IF
|
|
; A CARRIAGE RETURN IS ENTER~D THE ROUTINE IS TERMINATE
|
|
; IF A SPACE OR COMMA IS ENTER~D, THE ROUTINE
|
|
; PROCEEDS TO THE NEXT LOCATION AND PRESENTS THE USER
|
|
; WITH AN OPPORTUNITY TO ALTER IT.
|
|
;
|
|
SUBS: CALL EXPR1 ;GO GET ONE PARAMETER
|
|
POP H ;GET THE START ADDRESS
|
|
SUB1: MOV A,M ;GET THE CONTENTS OF THE ADDRESS
|
|
CALL DASH1 ;DISPLAY IT ON CONSOLE AND A DASH
|
|
CALL PCHK ;GET CHECK CHARACTER
|
|
RC ;DONE IF CARRIAGE RETURN
|
|
JRZ SUB2 ;NO CHANGE IF BLANK OR
|
|
;
|
|
CPI LF ;SEE IF PREVIOUS BYTE WANTED
|
|
JRZ SUB3 ;YES, DO IT
|
|
;
|
|
PUSH H ;SAVE MEMORY POINTER
|
|
CALL EXF ;GO GET REST OF NEW VALUE
|
|
POP D ;NEW VALUE TO E REGISTER
|
|
POP H ;RESTORE MEMORY POINTER
|
|
MOV M,E ;PUT DOWN NEW VALUE
|
|
MOV A,C ;GET THE DELIMITER
|
|
CPI CR ;SEE IF DONE (CARRIAGE RETURN)
|
|
RZ ;YES, RETURN TO MONITOR
|
|
SUB2: INX H ;NO INCREMENT MEMORY PONTER
|
|
INX H ;ALLOW A FALL THROUGH ON THE NEXT INST
|
|
SUB3: DCX H ;ADJUST (H,L) AS APPROPRIATE
|
|
MOV A,L ;GET LO ADDRESS BYTE
|
|
ANI 7 ;SEE IF ON A BOUNDARY
|
|
CZ LADRB ;CALL IF ON THE BOUNDARY
|
|
JMPR SUB1 ;GO DO THE NEXT LOCATION
|
|
;
|
|
;
|
|
; MTEST ROUTINE TESTS A SPECIFIED BLOCK OF MEMORY TO
|
|
; SEE IF ANY HARD DATA BIT FAILURES EXIST. IT IS
|
|
; NOT AN EXHAUSTIVE TEST BUT JUST A QUICK INDICATION
|
|
; OF THE MEMORY'S OPERATVENESS.
|
|
;
|
|
MTEST: CALL EXLF
|
|
MTEST1: MOV A,M ;READ A BYTE
|
|
PUSH PSW ;SAVE IT
|
|
CMA ;COMPLEMENT IT
|
|
MOV M,A ;WRITE IT
|
|
XRA M ;RESULT SHOULD BE ZERO
|
|
CNZ BITS ;LOG ERROR IF NOT
|
|
MTEST2: POP PSW
|
|
MOV M,A ;RESTORE ORIGINAL BYTE
|
|
CALL HILOX ;PONT TO NEXT AND SEE IF DONE
|
|
JMPR MTEST1 ;NO, CONTINUE
|
|
;
|
|
BITS: PUSH D ;SAVE (D,E)
|
|
MOV E,A ;SAVE ERROR PATTERN IN E
|
|
CALL LADRB ;FIRST PRINT THE ADDRESS
|
|
BITS2: MVI B,8 ;LOOP CONTROL FOR 8 BITS
|
|
BITS1: MOV A,E ;GET NEXT BIT
|
|
RLC ; INTO CARRY
|
|
MOV E,A ;SAVE REST
|
|
MVI A,'0'/2 ;BUILD ASCII 1 OR 0
|
|
RAL ; CARRY DETERMINES WHICH
|
|
MOV C,A ;NOW, OUTPUT IT
|
|
CALL CONOUT
|
|
DJNZ BITS1 ;DO IT AGAIN
|
|
;
|
|
POP D
|
|
RET
|
|
;
|
|
; EXAMINE REGISTERS COMMAND INSPECTS THE VALUES OF THE
|
|
; THE REGISTERS STORED BY THE LAST ENCOUNTERED BREAKPOINT.
|
|
; THE VALUES MAY BE MODIFIED IF DESIRED.
|
|
;
|
|
XAA: INX H ;SKIP OVER TO NEXT ENTRY
|
|
INX H
|
|
XA: INR M ;SEE IF AT END OF TABLE
|
|
RZ ;COULDN'T FIND MATCH, QUIT
|
|
JP XAB ;SORT OUT BIT 7 OF TABLE
|
|
ORI 80H ;SET IT ON TEST VALUE
|
|
JMPR XAC
|
|
;
|
|
XAB: ANI 7FH ;RESET BIT 7
|
|
XAC: DCR M ;TO BE PULLED OUT IN ROM
|
|
CMP M ;SEE IF THIS IS IT
|
|
JRNZ XAA ;NO, GO TRY AGAIN
|
|
;
|
|
CALL BLK ;YES PREPARE TO SHOW CURRENT VALUE
|
|
CALL PRTVAL ;GO PRINT THE VALUE
|
|
CALL DASH ;PROMPT A NEW VALUE
|
|
CALL PCHK ;GET THE INPUT
|
|
RC ;DONE IF CARRIAGE RETURN
|
|
JRZ XF ;JUMP IF NO CHANGE DESIRED
|
|
;
|
|
PUSH H ;TO BE CHANGED, SAVE POINTER
|
|
CALL EXF ;GET THE NEW VALUE
|
|
POP H ; INTO (H,L)
|
|
MOV A,L ;GET THE N~W LOW BYTE
|
|
INX D ;ADJUST POINTER
|
|
STAX D ;PUT IT DOWN
|
|
XTHL ;RECOVER THE TABLE POINTER
|
|
MOV A,M ;GET THE ATTRIBUTES
|
|
XTHL ;SET THE STACK STRAIGHT
|
|
RLC ;SEE IF 8 BIT REGISTER
|
|
JRNC XE ;JUMP IF SO
|
|
;
|
|
INX D ;REGISTER PAIR, DO OTHER 8 BITS
|
|
MOV A,H
|
|
STAX D
|
|
XE: POP H ;RESTORE THE TABLE POINTER
|
|
XF: MOV A,C ;SEE IF IT WAS A CR
|
|
CPI CR
|
|
RZ ;DONE IF SO
|
|
XMNE: LXI H,ACTBL ;GET ADDRESS OF REGISTER LOOK-UP TABLE
|
|
XMNE1: CALL PCHK ;FIND OUT WHAT ACTION IS WANTED
|
|
JRC XG ;SHOW ALL IF CARRIAGE RETURN
|
|
;
|
|
JRZ XMNE1 ;IGNORE BLANKS OR COMMAS
|
|
CPI '''' ;SEE IF PRIMES WANTED
|
|
JRNZ XA ;NO, MUST BE SINGLE REGISTER
|
|
;
|
|
LXI H,PRMTB ;YES, SET TABLE ADDRESS
|
|
JMPR XMNE1 ; AND FIND OUT WHICH ONE
|
|
;
|
|
XG: MOV A,M
|
|
MOV C,A
|
|
INR A ;SEE IF AT END OF TABLE
|
|
RZ ;DONE IF SO
|
|
CM CRLF ;START A NEW LINE IF BIT 7 IS SET
|
|
CALL CONOUT
|
|
CALL DASH ;PROMPT FOR A NEW VALUE
|
|
CALL PRTVAL ;GO PRINT THE VALUE
|
|
CALL BLK ;FORMATTER
|
|
INX H ;POINT TO NEXT ENTRY
|
|
JMPR XG ;DO THE NEXT VALUE
|
|
;
|
|
PRTVAL: INX H ;POINT TO NEXT ENTRY
|
|
MOV A,M ;GET OFFSET AND ATTRIBUTES BYTE
|
|
ANI 3FH ;ISOLATE THE OFFSET
|
|
ADI 2 ;ALLOW FOR RETURN ADDRESS
|
|
XCHG ;RE-SWAP POINTERS
|
|
MOV L,A ;BUILD THE ADDRESS OF THE REQ CONTENTS
|
|
MVI H,0
|
|
DAD SP
|
|
XCHG ;RE-SWAP THE POINTERS
|
|
MOV A,M ;NOW FIND OUT ATTRIBUTES
|
|
MVI B,1 ;SET UP FOR SINGLE REG VALUE
|
|
RLC
|
|
JRNC PV1 ;JUMP IF SINGLE REGISTER VALUE WANTED
|
|
;
|
|
INR B ;SET UP FOR REGISTER PAIR
|
|
RLC
|
|
JRNC PV1 ;JUMP IF REGISTER PAIR IS NEXT
|
|
;
|
|
PUSH H ;SPECIAL CASE FOR MEMORY REGISTER
|
|
LDAX D ;BUILD ADDRESS IN (H,L)
|
|
MOV H,A
|
|
DCX D
|
|
LDAX D
|
|
MOV L,A
|
|
MOV A,M ;GET THE MEMORY VALUE
|
|
POP H ;RESTORE (H,L)
|
|
DJNZ PV2 ;ALWAYS JUMP
|
|
;
|
|
PV1: LDAX D ;GET THE REGISTER CONTENTS
|
|
PV2: CALL HEX1 ;OUTPUT THE VALUE
|
|
DCX D ;ADJUST THE MEMORY POINTER
|
|
DJNZ PV1
|
|
;
|
|
RET
|
|
;
|
|
ACTBL: DB 80H+'A',ALOC
|
|
DB 'B',BLOC
|
|
DB 'C',CLOC
|
|
DB 'D',DLOC
|
|
DB 'E',ELOC
|
|
DB 'F',FLOC
|
|
DB 'H',HLOC
|
|
DB 'L',LLOC
|
|
DB 80H+'M',HLOC+0C0H
|
|
DB 'P',PLOC+80H
|
|
DB 'S',SLOC+80H
|
|
DB 'I',ILOC
|
|
;
|
|
; REST OF Z 80 REGISTER OFFSETS
|
|
;
|
|
PRMTB: DB 80H+'A',APLOC
|
|
DB 'B',BPLOC
|
|
DB 'C',CPLOC
|
|
DB 'D',DPLOC
|
|
DB 'E',EPLOC
|
|
DB 'F',FPLOC
|
|
DB 'H',HPLOC
|
|
DB 'L',LPLOC
|
|
DB 80H+'M',HPLOC+0C0H
|
|
DB 'X',XLOC+80H
|
|
DB 'Y',YLOC+80H
|
|
DB 'R',RLOC
|
|
DB 0FFH
|
|
;
|
|
; GENERAL PURPOSE ROUTINES
|
|
;
|
|
;
|
|
; ROUTINE CONV CONVERTS THE LOW ORDER NIBBLE OF THE
|
|
; ACCUMULATOR TO ITS ASCII EQUIVALENT. IT
|
|
; PUTS THE RESULT INTO C FOR LATER OUTPUT.
|
|
;
|
|
CONV: ANI 0FH ;STRIP OFF BITS 4 7
|
|
ADI 90H ;PUT ON THE ASCII ZONE
|
|
DAA
|
|
ACI 40H
|
|
DAA
|
|
MOV C,A ;PUT IN OUTPUT PASS REGISTER
|
|
RET
|
|
;
|
|
; ROUTINE ECHO READS A BYTE FROM A HALF DUPLEX CONSOLE
|
|
; DEVICE THEN ECHOES THE CHARACTER BACK TO THE
|
|
; CONS0LE.
|
|
;
|
|
DECHO: CALL DASH ;PRINT A DASH
|
|
ECHO: CALL CONI ;CONSOLE READ, WRITE ROUTINE
|
|
ECH1: PUSH B ; SAVE (B,C)
|
|
MOV C,A ; PASS CHARACTER IN C REGISTER
|
|
CALL CONOUT ; OUTPUT IT
|
|
MOV A,C ; PUT CHARACTER BACK INTO A
|
|
POP B ; RESTORE (B,C)
|
|
RET
|
|
;
|
|
; ROUTINE EXPR3 GETS THREE PARAMETERS, DOES A CR LF AND
|
|
; THEN LOADS (B,C), (D,E), AND (H,L) WITH THE PARAMETERS.
|
|
EXPR3: INR B ;2 IS ALREADY IN THE B REGISTER
|
|
CALL EXPR ;GET THE PARAMETERS
|
|
POP B ;PUT PARAMETERS INTO REGISTERS
|
|
POP D
|
|
JMP CRLFA ;GO DO THE CARRIAGE RETURN SEQUENCE
|
|
;
|
|
; ROUTINE HILO INCREMENTS (H,L) IT THEN CHECKS FOR (AND
|
|
; DISALLOWS) A WRAP AROUND SITUATION. IF IT OCCURS,
|
|
; THE CARRY BIT WILL BE SET ON RETURN. IF NO WRAP-
|
|
; AROUND OCCURRED (H,L)IS COMPARED TO (D,E) AND
|
|
; THE FLAG BITS SET ACCORDINGLY.
|
|
HILO: INX H ;INCREMENT (H,L)
|
|
MOV A,H ;TEST IF ZERO
|
|
ORA L ; IN (H,L)
|
|
STC ;SET CARRY FOR (H,L)=0
|
|
RZ ;RETURN TF (H,L)=0
|
|
MOV A,E ;COMPARE(H,L) TO (D,E)
|
|
SUB L
|
|
MOV A,D
|
|
SBB H
|
|
RET ;RETURN WITH FLAGS SET
|
|
;
|
|
; ROUTINE HILOX INCREMENTS (H,L), COMPARES IT TO (D,E) AND
|
|
; IF EQUAL RETURNS CONTROL TO THE MONITOR EXECUThVE.
|
|
; OTHERWISE, CONTROL RETURNS TO THE CALLING ROUTINE.
|
|
;
|
|
HILOD: POP D ;GET RID OF RETURN ADDRESS
|
|
RET ;RETURN TO MONITOR
|
|
HILOXB: INX B ;INCREMENT (B,C)
|
|
HILOX: CALL HILO ;INC AND CHECK (H,L)
|
|
JRC HILOD ;DONE IF CARRY SET
|
|
;
|
|
CALL CONST ;SEE IF CONSOLE BREAK PENDING
|
|
ORA A
|
|
RZ ;NONE RETURN TO CONTINUE
|
|
CALL CONI ;SEE IF WAIT OR BREAK
|
|
CPI CTRLS
|
|
JRNZ HILOD ;JUMP IF BREAK
|
|
;
|
|
JMP CONI ;GO WAIT FOR NEXT CHARACTER
|
|
;
|
|
; ROUTINE NIBBLE CONVERTS THE ASCII CHARACTERS 0-9 AND
|
|
; A-F TO THEIR EQUIVALENT HEXADECIMAL VALUE. IF
|
|
; THE CHARACTER IS NOT IN RANGE, THE CARRY BIT IS SET TO
|
|
; FLAG THE ERROR.
|
|
NIBBLE: SUI '0' ;ASCII TO HEX CONVERSION
|
|
RC ; DONE IF OUT OF RANGE
|
|
CPI 'G'-'0' ;CHECK UPPER END
|
|
CMC ; TOGGLE THE CARRY BIT
|
|
RC ; DONE IF OUT OF RANGE
|
|
CPI '9'-'0'+1 ;SEE IF NUMERIC
|
|
CMC ; TOGGLE THE CARRY BIT
|
|
RNC ; DONE IF SO
|
|
SUI 'A'-'9'-1 ;SUBTRACT THE ALPHA BIAS
|
|
CPI 10 ; SET CARRY FOR INVALID CHAR
|
|
RET
|
|
;
|
|
; ROUTINE PCHK READS A CHARACTER FROM THE CONSOLE, THEN
|
|
; CHECKS IT FOR A DELIMITER. IF IT IS NOT
|
|
; A DELIMTTER A NON ZERO CONDITION IS RETURNED.
|
|
; IF IT IS A DELIMITER, A ZERO CONDITION IS RETURNED.
|
|
; FURTHER TF THE DELIMITER IS A CARRIAGE RETURN
|
|
; THE CARRY BIT IS SET. A BLANK OR A COMMA RESET'S
|
|
; THE CARRY BIT.
|
|
;
|
|
PCHK: CALL ECHO ;GET, TEST FOR DELIMITER
|
|
P2C: CPI ' ' ; BLANK?
|
|
RZ ; YES, DONE
|
|
CPI ',' ; NO COMMA?
|
|
RZ ; YES, DONE
|
|
CPI CR ; NO CARRIAGE RETURN?
|
|
STC ; SHOW IT IN CARRY BIT
|
|
RZ ; DONE IF CR
|
|
CMC ; CLEAR CARRY FOR NO DELIMITER
|
|
RET
|
|
;
|
|
; ROUTINE REST TRAPS ALL OF THE REGISTER CONTENTS WHENEVER A
|
|
; RESTART 1 INSTRUCTION IS EXECUTED. THE TRAPPED CONTEN
|
|
; ARE STORED IN THE SYSTEM STACK AREA FOR LATER ACCESS AND
|
|
; USE BY THE GOTO AND THE EXAMINE REGISTERS COMMANDS.
|
|
;
|
|
; INSERT INTERRUPT DISABLER SOFTWARE AT START OF REST:
|
|
REST: PUSH H ;SAVE ALL THE REGISTERS
|
|
PUSH D
|
|
PUSH B
|
|
PUSH PSW
|
|
CALL MEMSIZ ;GET THE MONITOR'S STACK LOCATION
|
|
XCHG
|
|
LXI H,10 ;GO UP 10 BYTES IN THE STACK
|
|
DAD SP ; TO SKIP OVER TEMP REGISTER SAVE
|
|
MVI B,4 ;PICK OFF THE REGISTER VALUES
|
|
XCHG
|
|
RS1: DCX H
|
|
MOV M,D ;SAVE IN WORK AREA
|
|
DCX H
|
|
MOV M,E
|
|
POP D
|
|
DJNZ RS1
|
|
;
|
|
POP B ;GET THE BREAKPOINT LOCATION
|
|
DCX B
|
|
SPHL ;SET THE MONITOR STACK
|
|
LXI H,TLOCX ;SET UP TO RESTORE BREAKPOINTS
|
|
DAD SP
|
|
PUSH D
|
|
MVI D,NBKPTS ;LOOP CONTROL F0R N BREAKPOINTS
|
|
RS2: MOV A,M
|
|
SUB C ;SEE IF A SOFTWARE TRAP
|
|
INX H
|
|
MOV A,M
|
|
SBB B ;MAYBE, TRY REST OF ADDRESS
|
|
JRZ RS5 ;FOUND ONE, JUMP TO RESET IT
|
|
;
|
|
RS3: INX H ;NOT FOUND, TRY NEXT ONE
|
|
INX H
|
|
DCR D
|
|
JRNZ RS2
|
|
;
|
|
RS4: INX B ;NONE FOUND
|
|
RS5: LXI H,LLOCX
|
|
POP D
|
|
DAD SP
|
|
MOV M,E ;STORE USER (H,L)
|
|
INX H
|
|
MOV M,D
|
|
PUSH B ;SAVE (B,C)
|
|
MVI C,'*' ;TYPE THE BREAK INDICATION
|
|
CALL CONOUT
|
|
POP D ;REGET THE BREAKPOINT LOCATION
|
|
MVI A,RS9/256
|
|
CMP D ;SEE IF A RET BREAKPOINT
|
|
JRZ RS6
|
|
;
|
|
INX H
|
|
INX H
|
|
MOV M,E ;RESTORE USER PROGRAM COUNTER
|
|
INX H
|
|
MOV M,D
|
|
XCHG ;PRINT THE BREAKPOINT LOCATION
|
|
CALL LADR
|
|
RS6: LXI H,TLOCX
|
|
DAD SP
|
|
LXI B,NBKPTS*256
|
|
RS7: MOV E,M ;RESTORE BREAKPOINTED LOCATIONS
|
|
MOV M,C ;RESET SYSTEM BP SAVE AREA
|
|
INX H
|
|
MOV D,M
|
|
MOV M,C
|
|
INX H
|
|
MOV A,E
|
|
ORA D
|
|
JRZ RS8 ;DO NOTHING IF ZERO
|
|
;
|
|
MOV A,M
|
|
STAX D
|
|
RS8: INX H ;SAME THING FOR OTHER
|
|
DJNZ RS7 ; BREAKPOINT
|
|
;
|
|
EXAF ;NOW SAVE THE Z-80 UNIQUES
|
|
EXX
|
|
;
|
|
PUSH H
|
|
PUSH D
|
|
PUSH B
|
|
PUSH PSW
|
|
PUSHIX
|
|
;
|
|
PUSHIY
|
|
;
|
|
LDAI
|
|
;
|
|
MOV B,A
|
|
LDAR
|
|
;
|
|
MOV C,A
|
|
PUSH B
|
|
JMP WINITA ;RETURN TO MONITOR
|
|
RS9: PUSH H ;RET BREAKPOINT ENCOUNTERED, ADJUST TH
|
|
RST 1 ;DO THE BREAKPOINT
|
|
EXIT: POP B
|
|
MOV A,C
|
|
STAR
|
|
;
|
|
MOV A,B
|
|
STAI
|
|
;
|
|
POPIX
|
|
;
|
|
POPIY
|
|
;
|
|
POP PSW
|
|
POP B
|
|
POP D
|
|
POP H
|
|
EXAF
|
|
;
|
|
EXX
|
|
;
|
|
POP D
|
|
POP B
|
|
POP PSW
|
|
POP H
|
|
SPHL
|
|
DB 0 ;PLACE FOR EI
|
|
LXI H,0
|
|
JMP 0
|
|
ENDX: EQU $
|
|
;
|
|
;ERROR HANDLERS
|
|
;
|
|
; THREE TYPES OF ERRORS ARE DETECTED: A RESTART
|
|
; ERROR AN I/O ASSIGNMENT ERROR AND CERTAIN PROGRAM
|
|
; ERRORS (DETERMINED BY THE PARTCULAR ROUTINE WHERE
|
|
; THE ERROR CONDITION WAS ENCOUNTERED.) EACH CAUSES
|
|
; A UNIQUE MESSAGE TO BE PRINTED, THEN DOES A WARM
|
|
; INITIALIZATION OF THE MONITOR. THE I/O ERROR
|
|
; CAUSES THE I/O ASSIGNMENTS TO BE RESET TO DEFAULT ASSI
|
|
IOER: XRA A ;SET IOBYTE TO DEFAULT VALUE
|
|
STA IOBYTE
|
|
LXI H,IOMSG ;GET ADDRESS OF I/O ERROR MSG
|
|
JMP COMERR ;GO PROCESS IT
|
|
IOMSG: DB 'I/O ER','R'+80H
|
|
;
|
|
; BYTE ROUTINE READS TWO ASCII CHARACTERS FROM THE
|
|
; CURRENT PAPER TAPE READER AND ASSEMBLES THEM INTO TWO
|
|
; HEXADECIMAL BYTES OF DATA. IT UPDATES A CHECKSUM
|
|
; ACCUMULATED IN REGISTER D.
|
|
BYTE: CALL BYT ;GET NEXT BYTE
|
|
ORA B ;COMBINE THEM
|
|
MOV B,A
|
|
ADD D ;UPDATE CHECKSUM
|
|
MOV D,A
|
|
MOV A,B ;RESTORE BYTE
|
|
RET
|
|
;
|
|
PEOL: MVI C,CR
|
|
CALL PO
|
|
MVI C,LF
|
|
JMP PO ;GO PUNCH THE OUTPUT
|
|
;
|
|
; RIX ROUTINE READS ONE CHARACTER FROM THE CURRENT
|
|
; PAPER TAPE READER AND STRIPS OFF THE PARITY BIT.
|
|
RIX: CALL RI
|
|
ANI 7FH
|
|
RET
|
|
QMSG: DB '???','?'+80H
|
|
LOGMSG: DB 'MOSS VERS 2.2'
|
|
DB CR,LF+80H
|
|
;
|
|
; INITIALIZATION CODE FOR THE 8250 ASYNCHRONOUS COMMUNICATION
|
|
; ELEMENT. THIS CODE WILL INITIALIZE THE BAUD RATE OF THE
|
|
; 8250, AS WELL AS THE WORD FORMAT. 8 DATA BTTS I STOP BIT
|
|
; AND NO PARITY ARE SELECTED. EITHER 2 OR 3 CARIAGE RETURNS
|
|
; MUST BE ENTERED TO ESTABLISH THE CORRECT BAUD RATE.
|
|
I8250: MVI A,0FH ;SET UP THE 8250
|
|
OUT SMDMCT
|
|
LXI D,40H ;SET UP TO TIME THE START BIT
|
|
MOV H,D
|
|
MOV L,D ;ZEROES TO (H,L)
|
|
I8250A: IN SMDMST ;WAIT FOR START BIT
|
|
ANA E
|
|
JRZ I8250A
|
|
;
|
|
I8250B: IN SMDMST ;NOW, TIME THE START BIT DURATION
|
|
INX H
|
|
ANA E
|
|
ANA E
|
|
JNZ I8250B
|
|
PUSH H ;SAVE COUNT IN CASE OF 4 MHZ
|
|
DAD H ;PREPARE THE 2 MHZ DIVISOR
|
|
MOV E,H ;SET UP THE FUDGE FACTOR
|
|
DAD D ;APPLY THE FUDGE FACTOR
|
|
DAD D
|
|
PUSH H ;SAVE FOR LATER USE
|
|
DAD H ;WAIT FOR 8 BIT TIMES
|
|
DAD H
|
|
I8250C: IN SDATA ;WASTE SOME TIME
|
|
DCX H
|
|
MOV A,L
|
|
ORA H
|
|
JNZ I8250C
|
|
POP H ;REGET 2 MHZ DIVISOR
|
|
I8250D: MVI A,83H ;SET DIVISOR REGISTER ACCESS
|
|
OUT SLCTRL
|
|
MOV A,L ;SET THE DIVISOR
|
|
OUT SDATA
|
|
MOV A,H
|
|
OUT SINTEN
|
|
MVI A,3 ;SET DATA REGISTER ACCESS
|
|
OUT SLCTRL
|
|
XRA A ;DISABLE INTERRUPTS
|
|
OUT SINTEN
|
|
OUT SLSTAT ;AND RESET ERROR FLAGS
|
|
CALL TTYIN ;GET A CHARACTER
|
|
ANI 7FH ;STRIP OFF ANY PARITY BIT
|
|
CPI 0DH ;SEE IF IT IS A CARRIAGE RETURN
|
|
POP H ;SET THE STACK STRAIGHT
|
|
RZ ;DONE IF CARRIAGE RETURN RECEIVED
|
|
MOV E,L ;ELSE, MUST BE 4 MHZ SYSTEM
|
|
MOV D,H ; SO, COUNT=COUNT*5/4
|
|
CALL DIV2
|
|
CALL DIV2
|
|
DAD D
|
|
PUSH H
|
|
JMPR I8250D ;GO SET THE NEW DIVISOR
|
|
;
|
|
;
|
|
;
|
|
DIV2: ORA A ;CLEAR THE CARRY BIT
|
|
MOV A,H ;DO A 16 BIT RIGHT SHIFT
|
|
RAR
|
|
MOV H,A
|
|
MOV A,L
|
|
RAR
|
|
MOV L,A
|
|
RET
|
|
;
|
|
; EOF ROUTINE PUNCHES AN END OF FILE RECORD (INTEL HEX
|
|
; FORMAT) ONTO THE CURRENTLY ASSIGNED PAPER TAPE PUNCH
|
|
; DEVICE. AN ENTRY POINT ADDRESS FOR THE FILE WILL ALSO
|
|
; BE PUNCHED, IF SPECIFIED.
|
|
;
|
|
EOF: CALL EXLF ;GET JUMP ADDRESS
|
|
PUSH D ;SAVE THE # OF TRAILER NULLS
|
|
EOFA: CALL PSOR ;PUNCH START OF RECORD
|
|
XRA A ;ZERO OUT THE CHECKSUM
|
|
MOV D,A
|
|
CALL PBADR ;OUTPUT THE RECORD LENGTH AND EP
|
|
MVI A,1 ;PUNCH RECORD TYPE = 1
|
|
CALL PBYTE
|
|
XRA A
|
|
SUB D ;OUTPUT THE CHECKSUM
|
|
CALL PBYTE
|
|
JMPR LEO ;GO DO THE TRAILER
|
|
;
|
|
;
|
|
; LEADER ROUTINE 'PUNCHES' SIX INCHES (OR AS SPECIFIED)
|
|
; OF LEADER ON THE PAPER TAPE PUNCH. NULLS ARE PUNCHED
|
|
; TO FORM THE LEADER (OR TRAILER).
|
|
;
|
|
LEADER: CALL EXPR1 ;SEE IF SOME OTHER LENGTH WANTED
|
|
LEO: POP B ;GET THE VALUE
|
|
MOV A,B
|
|
ORA C ;TEST FOR DEFAULT SELECT
|
|
MOV B,C ;MOVE NEW VALUE IN JUST IN CASE
|
|
MVI C,0 ;GET A NULL CHARACTER
|
|
JRNZ LE1 ;JUMP IF NEW VALUE WANTED
|
|
;
|
|
MVI B,60 ;DEFAULT SET 60 NULLS
|
|
LE1: CALL PUNCH ;PUNCH ONE NULL
|
|
DJNZ LE1 ;KEEP GOING TIL DONE
|
|
;
|
|
RET
|
|
;
|
|
; QUERY ROUTINE WILL TELL THE OPERATOR WHAT HIS CURRENT LOGICAL
|
|
; PHYSICAL PERIPHERAL DEVICE ASSIGNMENTS ARE. NO PARAME
|
|
; (OTHER THAN A CARRIAGE RETURN) ARE REQUIRED ON ENTRY.
|
|
QUERY: LDA IOBYTE ;GET THE ASSIGNMENT CONTROL BYTE
|
|
MVI B,4 ;SET UP FOR FOUR LOGICAL DEVICES
|
|
LXI H,ACT ;ADDRESS OF CONVERSION TABLE
|
|
LXI D,ALT-APT ;NEGATIVE OFFSET FOR LOGICAL TABLE
|
|
QUE1: PUSH PSW
|
|
CALL BLK ;FORMAT THE PRINT OUT
|
|
MOV C,M ;GET THE CURRENT LOGICAL DEVICE CODE
|
|
CALL CONOUT ;OUTPUT IT
|
|
CALL DASH ;OUTPUT A DASH
|
|
POP PSW ;REGET THE CONTROL BYTE
|
|
PUSH PSW ;RESAVE IT
|
|
PUSH H ;SAVE THE TABLE POINTER
|
|
QUE2: INX H ;ADJUST POINTER TO CURRENT PHYSICAL DE
|
|
INR A
|
|
ANI 3 ;BITS 0 AND 1 ARE 0 WHEN ON CURRENT AS
|
|
JRNZ QUE2 ;NOT THERE YET, TRY AGAIN
|
|
;
|
|
MOV C,M ;FOUND IT, NOW PRINT IT
|
|
CALL CONOUT
|
|
POP H
|
|
POP PSW ;GO TO NEXT LOGICAL DEVICE
|
|
RAR ;ADJUST THE IOBYTE
|
|
RAR
|
|
DAD D ;ADJUST THE TABLE POINTER
|
|
DJNZ QUE1 ;GO DO NEXT LOGICAL DEVICE
|
|
;
|
|
RET ;RETURN TO MONITOR
|
|
;
|
|
; READ ROUTINE READS AN INTEL HEX FORMAT PAPER TAPE FROM
|
|
; THE CURRENT PAPER TAPE READER. IF A NON ZERO ADDRESS
|
|
; IS SPECIFIED IN THE END OF FILE RECORD CONTROL WILL
|
|
; BE TRANSFERRED TO THAT ADDRESS. OTHERWISE, CONTROL
|
|
; WILL REVERT TO THE EXECUTIVE.
|
|
;
|
|
READ: CALL EXPR1 ;GET OFFSET BIAS
|
|
REDO: POP H ; INTO (H,L)
|
|
PUSH H ;SAVE THE BIAS
|
|
RED1: CALL RIX ;READ A BYTE
|
|
SBI ':' ;LOOK FOR START OF RECORD
|
|
JRNZ RED1 ;JUMP TO KEEP LOOKING
|
|
;
|
|
MOV D,A ;INITIALIZE CHECKSUM
|
|
CALL BYTE ;GET RECORD LENGTH
|
|
JRZ RED3 ;JUMP IF EOF RECORD
|
|
;
|
|
MOV E,A ;ELSE, ASSUME DATA RECORD
|
|
CALL BYTE ;GET LOAD ADDRESS HIGH BYTE
|
|
PUSH PSW ;SAVE IT
|
|
CALL BYTE ;GET LOAD ADDRESS LOW BYTE
|
|
POP B ;BUILD ADDRESS IN (B,C)
|
|
MOV C,A
|
|
DAD B ;ADD ON THE BIAS
|
|
CALL BYTE ;SKIP OVER RECORD TYPE
|
|
RED2: CALL BYTE ;GET A DATA BYTE
|
|
MOV M,A ;PUT IT INTO MEMORY
|
|
CMA ;D0 A QUICK CHECK
|
|
XRA M ; RESULT SHOULD BE ZERO
|
|
CNZ BITS ;IF ERROR PRINT ADDRESS AND DATA
|
|
INX H ;INCREMENT MEMORY POINTER
|
|
DCR E ;RECORD LENGTH FOR LOOP CONTROL
|
|
JRNZ RED2 ;DO REST OF THE RECORD
|
|
;
|
|
CALL BYTE ;GET THE CHECKSUM
|
|
JNZ QPRT ;ABORT IF ERROR
|
|
JMPR REDO ;GO DO NEXT RECORD
|
|
;
|
|
RED3: CALL BYTE ;EOF RECORD GET ENTRY POINT
|
|
MOV H,A ;HIGH BYTE TO (H)
|
|
CALL BYTE ;GET THE LOW BYTE
|
|
MOV L,A
|
|
ORA H ;SEE IF IT IS ZERO
|
|
POP D ;RESTORE THE STACK
|
|
RZ ;RETURN TO MONITOR IF EP=0
|
|
PCHL ;ELSE, GO TO THE ENTRY POINT
|
|
;
|
|
; WRITE ROUTINE IS USED TO PUNCH AN INTEL HEX FORMAT
|
|
; PAPER TAPE ON THE CURRENT ASSIGNED PUNCH UNIT.
|
|
;
|
|
WRITE: CALL EXPR3 ;GET 3 PARAMETERS, DO CRLF
|
|
XRA A ;SEE IF RECORD LENGTH CHANGE
|
|
MOV B,A ;SET HIGH BYTE TO ZERO
|
|
ORA C ;NOW SEE IF CHANGE WANTED
|
|
JRNZ WRI1 ;YES, JUMP AND SET IT UP
|
|
;
|
|
MVI C,16 ;NO, DEFAULT TO 16 BYTES/RECORD
|
|
WRI1: PUSH H ;SAVE MEMORY POINTER
|
|
DAD B ;ADD THE RECORD LENGTH
|
|
ORA A ;CLEAR THE CARRY BIT
|
|
DSBC D ;SEE IF FULL RECORD REMAINS
|
|
;
|
|
POP H ;RESTORE (H,L)
|
|
JRC WRI2 ;GO DO A FULL RECORD
|
|
PUSH D ;SAVE LAST BYTE ADDRESS
|
|
XCHG ;SWAP (D,E) AND(H,L)
|
|
ORA A ;RESET THE CARRY BIT
|
|
DSBC D ;FIND # OF BYTE REMAINING
|
|
;
|
|
INX H ;ADJUST TO INCLUDE LAST BYTE
|
|
XTHL ;SWAP TOP OF STACK
|
|
XCHG ;SET (D,E) (H,L) TO NORMAL
|
|
POP B ;NEW RECORD LENGTH TO (B,C)
|
|
RC ;DONE IF ZERO LENGTH RECORD
|
|
WRI2: PUSH B ;SAVE LOOP COUNT
|
|
PUSH D
|
|
MOV D,B ;ZERO THE CHECKSUM
|
|
MOV B,C ;MOVE LOOP CONTROL TO B
|
|
CALL PSOR ;PUNCH START OF RECORD
|
|
MOV A,B ;GET RECORD LENGTH
|
|
CALL PBADR ;PUNCH IT
|
|
XRA A ;PUNCH RECORD TYPE '0'
|
|
CALL PBYTE
|
|
WRI3: MOV A,M ;GET NEXT DATA BYTE
|
|
INX H ;BUMP THE POINTER
|
|
CALL PBYTE ;PUNCH THE DATA
|
|
DJNZ WRI3 ;DO REST OF RECORD
|
|
;
|
|
XRA A ;NOW, DO THE CHECKSUM
|
|
SUB D
|
|
CALL PBYTE ;PUNCH IT
|
|
POP D ;RESTORE THE REGISTERS
|
|
POP B
|
|
JMPR WRI1 ;GO DO NEXT RECORD
|
|
;
|
|
PSOR: CALL PEOL
|
|
MVI C,':'
|
|
JMP PO
|
|
;
|
|
; HEXN ROUTINE
|
|
;
|
|
;THIS ROUTINE ADDS AND SUBTRACTS TWO HEXADECIMAL 16 BIT
|
|
; UNSIGNED NUMBERS AND DISPLAYS THE RESULTS ON THE
|
|
; CONSOLE.
|
|
HEXN: CALL EXLF ;GET THE TWO NUMBERS
|
|
PUSH H ;SAVE IT FOR THE SUBTRACT
|
|
DAD D ;ADD THEM
|
|
CALL LADRB ;OUTPUT THEM
|
|
POP H ;REGET THE FIRST NUMBER
|
|
ORA A ;CLEAR THE CARRY BIT
|
|
DSBC D ;DO THE SUBTRACT
|
|
;
|
|
JMPR LADR ;GO OUTPUT THE RESULT
|
|
;
|
|
;
|
|
; ROUTINE LADR PRINTS THE CONTENTS OF (H,L) ON THE
|
|
; CURRENT CONSOLE EITHER AT THE SART OF A NEW
|
|
; LINE (EP = LADRA) OH AT THE CURRENT LOCATION (EP =
|
|
; LADR).
|
|
LADRA: CALL CRLF ;START A NEW LINE
|
|
LADR: MOV A,H ;GET HIGH TWO DIGITS
|
|
CALL HEX1 ;PRNT THEM
|
|
MOV A,L ;GET LOW TWO DIGITS
|
|
HEX1: PUSH PSW ;SAVE THE LOW DIGIT
|
|
RRC ;PUT HIGH NIBBLE INTO BITS 0-3
|
|
RRC
|
|
RRC
|
|
RRC
|
|
CALL HEX2 ;GO PRINT SINGLE DIGIT
|
|
POP PSW ;REGET THE LOW DIGIT
|
|
HEX2: CALL CONV ;GO INSERT ASCII ZONE
|
|
JMPR CO ;DO THE CHARACTER OUTPUT
|
|
;
|
|
;
|
|
; ROUTINE DASH TYPES A DASH ON THE CURRENT CONSOLE DEVICE.
|
|
;
|
|
DASH1: CALL HEX1 ;FIRST, PRINT ACCUM AS TWO HEX DIGITS
|
|
DASH: MVI C,'-' ;GET AN ASCII DASH
|
|
JMPR CO ;GO TYPE IT
|
|
;
|
|
;
|
|
; IOBYTE HANDLERS
|
|
;
|
|
ORG MOSS + 05FBH
|
|
LADRB: CALL LADRA ;OUTPUT (H,L) AS 4 ASCII DIGITS
|
|
BLK: MVI C,' ' ;OUTPUT A BLANK
|
|
CO: LDA IOBYTE
|
|
ANI 3 ;ISOLATE CONSOLE ASGT
|
|
JZ TTYOUT ;TTY DEVICE ACTIVE
|
|
CPI 2
|
|
JM CRTOUT ;CRT ACTIVE
|
|
JNZ CUSO1 ;USER CONSOLE 1 ACTIVE
|
|
LO: LDA IOBYTE
|
|
ANI 0C0H ;ISOLATE LIST ASGT
|
|
JZ TTYOUT ;TTY DEVICE ACTIVE
|
|
CPI 80H
|
|
JM CRTOUT ;CRT ACTIVE
|
|
JZ LPRT ;LINE PRINTER ACTIVE
|
|
JMP LUSE1 ;USER PRINTER 1 ACTIVE
|
|
;
|
|
CSTS: LDA IOBYTE
|
|
ANI 3 ;ISOLATE CONSOLE ASGT
|
|
JZ TTST ;TTY ACTIVE
|
|
CPI 2
|
|
JM CRTST ;CRT ACTIVE
|
|
JNZ CUST1 ;USER CONSOLE 1 ACTIVE
|
|
;
|
|
BATST: LDA IOBYTE
|
|
ANI 0CH ;ISOLATE BATCH ASGT
|
|
JZ TTST ;TTY ACTIVE
|
|
CPI 8
|
|
JM PTRST ;PAPER TAPE READER ACTIVE
|
|
JZ RUST1 ;USER READER 1 ACTIVE
|
|
JMP RUST2 ;USER READER 2 ACTIVE
|
|
;
|
|
CI: LDA IOBYTE
|
|
ANI 3 ;ISOLATE CONSOLE ASGT
|
|
JZ TTYIN ;TTY DEVICE ACTIVE
|
|
CPI 2
|
|
JM CRTIN ;CRT ACTIVE
|
|
JNZ CUSI1 ;USER CONSOLE 1 ACTIVE
|
|
;
|
|
RI: LDA IOBYTE
|
|
ANI 0CH ;ISOLATE BATCH ASGT
|
|
JZ TTYRDR ;TTY ACTIVE
|
|
CPI 8
|
|
JM PTRIN ;PAPER TAPE READER ACTIVE
|
|
JZ RUSI1 ;USER READER I ACTIVE
|
|
JMP RUSI2 ;USER READER 2 ACTIVE
|
|
;
|
|
LSTAT: LDA IOBYTE
|
|
ANI 0C0H ;ISOLATE THE LIST DEVICE ASSIGNMENT
|
|
JZ TTOST
|
|
CPI 80H
|
|
JM CRTOST
|
|
JZ LPRST
|
|
JMP LUST1
|
|
;
|
|
PO: LDA IOBYTE
|
|
ANI 30H ;ISOLATE PUNCH ASGT
|
|
JZ TTPNCH ;TTY ACTIVE
|
|
CPI 20H
|
|
JM HSP ;HIGH SPEED PUNCH ACTIVE
|
|
JZ PUSO1 ;USER PUNCH 1 ACTIVE
|
|
JMP PUSO2 ;USER PUNCH 2 ACTIVE
|
|
;
|
|
; ROUTINE CONI READS THE CONSOLE AND STRIPS OFF THE ASCII
|
|
; PARITY BIT.
|
|
;
|
|
CONI: CALL CI ;GET THE NEXT CHARACTER
|
|
ANI 7FH ;STRIP OFF THE PARITY BIT
|
|
RTS: RET
|
|
;
|
|
; ROUTINE PRTWD PRINTS AN ASCII STRING ONTO THE CONSOLE.
|
|
; THE STRING MUST BE TERMINATED BY BIT 7 SET IN THE
|
|
; LAST CHARACTER OF THE STRING. THE STRING WILL START
|
|
; A NEW LINE (EP = PRTWD) OR CONTINUE ON THE SAME
|
|
; LINE (EP = PRTWA)
|
|
PRTWD: CALL CRLF ;START A NEW LINE
|
|
PRTWA: PUSH B ;SAVE (B,C)
|
|
PRTA: MOV C,M ;GET NEXT CHARACTER FROM MEMORY
|
|
CALL CO ;OUTPUT IT
|
|
INX H ;INCREMENT MEMORY POINTER
|
|
MOV A,C
|
|
RLC ;TEST FOR BIT 7 DELIMITER
|
|
JRNC PRTA ;NO DELIMITER, GO DO NEXT CHARACTER
|
|
;
|
|
PRTB: POP B ;RESTORE (B,C)
|
|
RET
|
|
;
|
|
; ROUTINE EXLF READS TWO PARAMETERS, PUTS THEM INTO THE
|
|
; D,E AND H,L REGISTERS, THEN DOES A CARRIAGE RETURN,
|
|
; LINE FEED SEQUENCE.
|
|
;
|
|
EXLF: CALL EXPR ;GO GET TWO PARAMETERS
|
|
POP D
|
|
POP H
|
|
;
|
|
; ROUTINE CRLF GENERATES A CARRIAGE RETURN, LNE FEED
|
|
; SEQUENCE ON THE CURRENT CONSOLE TO START A NEW LINE
|
|
; IT INCLUDES TRHEE NULL CHARACTERS FOR TTY TYPE
|
|
; DEVICES FOR THE HEAD MOVEMENT TIME.
|
|
;
|
|
CRLF: PUSH H ;SAVE THE CONTENTS OF (H,L)
|
|
CRLFA: LXI H,CRMSG ;ADDRESS OF CR,LF MESSAGE
|
|
CALL PRTWA ; OUTPUT IT
|
|
POP H ;RESTORE (H,L)
|
|
RET
|
|
;
|
|
RSTER: LXI H,RSTMSG ;GET ADDRESS OF RESTART ERROR MSG
|
|
COMERR: CALL PRTWD ;PRINT IT ON NEW LINE
|
|
JMP WSVEC ;GO TO WARM BOOT
|
|
RSTMSG: DB 'RST ER','R'+80H
|
|
CRMSG: DB CR,LF,0,80H
|
|
;
|
|
; I/O DRIVERS FOR THE 8250 ASYNC COMM ELEMENT
|
|
;
|
|
TTST: IN SLSTAT ;GET 8250 LINE STATUS
|
|
ANI 1 ;SEE IF RECEIVE DATA AVAILABLE
|
|
RZ ;RETURN IF NOT
|
|
ADI 0FEH ;FLAG THAT DATA IS AVAILABLE
|
|
RET
|
|
;
|
|
TTYIN: IN SLSTAT ;GET 8250 LINE STATUS
|
|
RAR ;MOVE RX DATA READY BIT INTO CARRY
|
|
JRNC TTYIN ;LOOP UNTIL DATA IS IN
|
|
;
|
|
IN SDATA ;READ THE DATA
|
|
RET
|
|
;
|
|
TTOST: IN SLSTAT ;GET 8250 LINE STATUS
|
|
ANI 20H ;ISOLATE TX BUFFER EMPTY BIT
|
|
RZ ;RETURN IF NOT EMPTY
|
|
ADI 0BFH ;FLAG THE EMPTY STATE
|
|
RET
|
|
;
|
|
TTYOUT: IN SLSTAT ;GET 8250 LINE STATUS
|
|
ANI 20H ;ISOLATE THRE BIT
|
|
JRZ TTYOUT ;WAIT UNTIL ONE OF THE REGISTERS EMPTI
|
|
;
|
|
MOV A,C ;MOVE THE DATA OVER
|
|
OUT SDATA ;OUTPUT THE DATA
|
|
RET
|
|
;
|
|
; EQUATES FOR ADDITIONAL CONSOLE DEVICES
|
|
CRTIN EQU IOER
|
|
CRTOUT EQU IOER
|
|
CRTST EQU IOER
|
|
CRTOST EQU IOER ;UNASSIGNED CRT OUTPUT STATUS
|
|
CUSI1 EQU IOER ;UNASSIGNED USER CONSOLE (INPUT)
|
|
CUSO1 EQU IOER ;UNASSIGNED USER CONSOLE (OUTPUT)
|
|
CUST1 EQU IOER
|
|
;
|
|
; EQUATES FOR ADDITIONAL PAPER TAPE PUNCH DEVICES
|
|
TTPNCH EQU TTYOUT ;UNASSIGNED TELETYPE PUNCH
|
|
HSP EQU IOER ;UNASSIGNED HIGH SPEED PUNCH
|
|
HSPST EQU IOER ;UNASSIGNED HJGH SPEED PUNCH STATUS
|
|
PUSO1 EQU IOER ;UNASSIGNED USER PUNCH 1
|
|
PUSO2 EQU IOER ;UNASSIGNED USER PUNCH 2
|
|
;
|
|
; EQUATES FOR ADDITIONAL LIST DEVICES
|
|
LPRT EQU IOER ;UNASSIGNED LINE PRINTER
|
|
LPRST EQU IOER ;UNASSIGNED PRINTER STATUS
|
|
LUSE1 EQU IOER ;LIST DEVICE 1
|
|
LUST1 EQU IOER ;LIST DEVICE 1 STATUS
|
|
;
|
|
; EQUATES FOR ADDITIONAL PAPER TAPE READER DEVICES
|
|
TTYRDR EQU TTYIN ;UNASSIGNED TELETYPE PAPER TAPE READER
|
|
PTRIN EQU IOER ;UNASSIGNED HIGH SPEED PAPER TAPE READ
|
|
PTRST EQU IOER ;UNASSIGNED HS PTR STATUS
|
|
RUSI1 EQU IOER ;UNASSIGNED PAPER TAPE READER 1
|
|
RUST1 EQU IOER ;UNASSIGNED PAPER TAPE READER 1 (STATUS)
|
|
RUSI2 EQU IOER ;UNASSIGNED PAPER TAPE READER 2
|
|
RUST2 EQU IOER ;UNASSIGNED PAPER TAPE READER 2 (STATUS)
|
|
;
|
|
BYT: CALL RIBBLE ;READ AND CONVERT ONE CHARACTER
|
|
RLC ;SHIFT INTO HIGH NIBBLE
|
|
RLC
|
|
RLC
|
|
RLC
|
|
MOV B,A ;SAVE IN B TEMPORARILY
|
|
RIBBLE: CALL RIX ;READ A CHARACTER
|
|
JMP NIBBLE ;GO CONVERT TO HEX DIGIT
|
|
;
|
|
; PADR ROUTINE PUNCHES (H,L) AS FOUR ASCII CHARACTERS.
|
|
; IT IS USED TO PUT THE ADDRESS INTO AN INTEL HEX
|
|
; FORMAT RECORD.
|
|
;
|
|
PBADR: CALL PBYTE
|
|
PADR: MOV A,H
|
|
CALL PBYTE
|
|
MOV A,L
|
|
;
|
|
; PBYTE ROUTINE PUNCHES (A) AS TWO ASCII CHARACTERS ON
|
|
; THE CURRENT PUNCH DEVICE.
|
|
;
|
|
PBYTE: PUSH PSW ;SAVE THE BYTE
|
|
RRC ;DO HIGH NIBBLE FIRST
|
|
RRC
|
|
RRC
|
|
RRC
|
|
CALL CONV ;CONVERT TO ASCII
|
|
CALL PUNCH ;PUNCH IT
|
|
POP PSW ;GET LOW NIBBLE
|
|
PUSH PSW ;RESAVE F0R CHECKSUM
|
|
CALL CONV ;CONVERT TO ASCII
|
|
CALL PUNCH ;PUNCH IT
|
|
POP PSW
|
|
ADD D ;UPDATE CHECKSUM
|
|
MOV D,A
|
|
RET
|
|
;
|
|
END
|