mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-22 16:04:18 +00:00
1646 lines
32 KiB
NASM
1646 lines
32 KiB
NASM
TITLE 'CP/M DEBUGGER (DEMON) 1/80'
|
|
; CP/M DEBUGGER VERSION 2.2
|
|
;
|
|
; COPYRIGHT (C) 1980
|
|
; DIGITAL RESEARCH
|
|
; BOX 579 PACIFIC GROVE
|
|
; CALIFORNIA 93950
|
|
;
|
|
FALSE EQU 0
|
|
TRUE EQU NOT FALSE
|
|
DEBUG EQU FALSE ;TRUE IF DEBUGGING
|
|
RELOC EQU TRUE ;TRUE IF RELOCATING
|
|
IF DEBUG
|
|
ORG 1000H
|
|
ELSE
|
|
IF RELOC
|
|
ORG 0000H
|
|
ELSE
|
|
ORG 0D000H ;TESTING IN 64K
|
|
ENDIF
|
|
ENDIF
|
|
;
|
|
MODBAS EQU $ ;BASE OF ASSEM/DISASSEM MODULE
|
|
DS 680H ;SIZE OF ASSEM/DISASSEM
|
|
DEMON EQU $ ;BASE OF DEMON MODULE
|
|
DISIN EQU MODBAS+3
|
|
BDOS EQU $+1006H
|
|
BDOSE EQU 5H ;ENTRY POINT TO DOS FROM USER PROGRAMS
|
|
PCBASE EQU 100H ;DEFAULT PC
|
|
SPBASE EQU 100H ;DEFAULT SP
|
|
DISEN EQU DISIN+3 ;DISASSEMBLER ENTRY POINT
|
|
ASSEM EQU DISEN+3 ;ASSEMBLER ENTRY POINT
|
|
DISPC EQU ASSEM+3 ;DISASSEMBLER PC VALUE
|
|
DISPM EQU DISPC+2 ;DISASSEMBLER PC MAX VALUE
|
|
DISPG EQU DISPM+2 ;DISASSEMBLER PAGE MODE IF NON ZERO
|
|
PSIZE EQU 12 ;NUMBER OF ASSEMBLY LINES TO LIST WITH 'L'
|
|
CSIZE EQU 32 ;COMMAND BUFFER SIZE
|
|
SSIZE EQU 50 ;LOCAL STACK SIZE
|
|
;
|
|
; BASIC DISK OPERATING SYSTEM CONSTANTS
|
|
CIF EQU 1
|
|
COF EQU 2
|
|
RIF EQU 3
|
|
POF EQU 4
|
|
LOF EQU 5
|
|
;
|
|
IDS EQU 7
|
|
GETF EQU 10 ;FILL BUFFER FROM CONSOLE
|
|
CHKIO EQU 11 ;CHECK IO STATUS
|
|
LIFT EQU 12 ;LIFT HEAD ON DISK
|
|
OPF EQU 15 ;DISK FILE OPEN
|
|
RDF EQU 20 ;READ DISK FILE
|
|
DMAF EQU 26 ;SET DMA ADDRESS
|
|
;
|
|
DBP EQU 5BH ;DISK BUFFER POINTER
|
|
DBF EQU 80H ;DISK BUFFER ADDRESS
|
|
DFCB EQU 5CH ;DISK FILE CONTROL BLOCK
|
|
FCB EQU DFCB
|
|
FDN EQU 0 ;DISK NAME
|
|
FFN EQU 1 ;FILE NAME
|
|
FFT EQU 9 ;FILE TYPE
|
|
FRL EQU 12 ;REEL NUMBER
|
|
FRC EQU 15 ;RECORD COUNT
|
|
FCR EQU 32 ;CURRENT RECORD
|
|
FLN EQU 33 ;FCB LENGTH
|
|
;
|
|
DEOF EQU 1AH ;CONTROL-Z (EOF)
|
|
CR EQU 0DH
|
|
LF EQU 0AH
|
|
;
|
|
IF DEBUG
|
|
RSTNUM EQU 6 ;USE 6 IF DEBUGGING
|
|
ELSE
|
|
RSTNUM EQU 7 ;RESTART NUMBER
|
|
ENDIF
|
|
RSTLOC EQU RSTNUM*8 ;RESTART LOCATION
|
|
RSTIN EQU 0C7H OR (RSTNUM SHL 3) ;RESTART INSTRUCTION
|
|
;
|
|
; TEMPLATE FOR PROGRAMMED BREAKPOINTS
|
|
; ---------
|
|
; PCH : PCL
|
|
; HLH : HLL
|
|
; SPH : SPL
|
|
; RA : FLG
|
|
; B : C
|
|
; D : E
|
|
; ---------
|
|
; FLG FIELD: MZ0I0E1C (MINUS,ZERO,IDC,EVEN,CARRY)
|
|
;
|
|
AVAL EQU 5 ;A REGISTER COUNT IN HEADER
|
|
BVAL EQU 6
|
|
DVAL EQU 7
|
|
HVAL EQU 8
|
|
SVAL EQU 9
|
|
PVAL EQU 10
|
|
;
|
|
;
|
|
; DEMON ENTRY POINTS
|
|
JMP TRAPAD ;TRAP ADDRESS FOR RETURN IN CASE INTERRUPT
|
|
JMP BEGIN
|
|
BREAKA:
|
|
JMP BREAKP
|
|
; USEFUL ENTRY POINTS FOR PROGRAMS RUNNING WITH DDT
|
|
JMP GETBUFF ;GET ANOTHER BUFFER FULL
|
|
JMP GNC ;GET NEXT CHARACTER
|
|
JMP PCHAR ;PRINT A CHARACTER FROM A
|
|
JMP PBYTE ;PRINT BYTE IN REGISTER A
|
|
JMP PADDX ;PRINT ADDRESS IN REGISTERS D,E
|
|
JMP SCANEXP ;SCAN 0,1,2, OR 3 EXPRESSIONS
|
|
JMP GETVAL ;GET VALUE TO H,L
|
|
JMP BREAK ;CHECK BREAK KEY
|
|
RET ;TAKES PLACE OF PRLABEL IN SID
|
|
;
|
|
;
|
|
TRAPAD: ;GET THE RETURN ADDRESS FOR THIS JUMP TO BDOS IN CASE OF
|
|
; A SOFT INTERRUPT DURING BDOS PROCESSING.
|
|
XTHL ;PC TO HL
|
|
SHLD RETLOC ;MAY NOT NEED IT
|
|
XTHL
|
|
TRAPJMP: ;ADDRESS FILLED AT "BEGIN"
|
|
JMP 0000H
|
|
;
|
|
BEGIN:
|
|
;
|
|
LHLD BDOSE+1
|
|
SHLD TRAPJMP+1 ;FILL JUMP TO BDOS
|
|
LXI H,TRAPAD
|
|
SHLD MODBAS+1 ;ADDRESS FIELD CHANGED
|
|
LXI H,MODBAS
|
|
SHLD BDOSE+1 ;NOW INCLUDES ASSEM/DISASSEM
|
|
;
|
|
XRA A ;ZERO TO ACCUM
|
|
STA BREAKS ;CLEARS BREAK POINT COUNT
|
|
;
|
|
LXI H,PCBASE
|
|
SHLD DISPC ;INITIAL VALUE FOR DISASSEMBLER PC
|
|
SHLD DISLOC ;INITIAL VALUE FOR DISPLAY
|
|
SHLD MLOAD ;MAX LOAD LOCATION
|
|
;
|
|
; SETUP RESTART TEMPLATE
|
|
SHLD PLOC
|
|
LXI H,SPBASE
|
|
LXI SP,STACK-4
|
|
PUSH H ;INITIAL SP
|
|
LXI H,10B ;INITIAL PSW
|
|
PUSH H
|
|
DCX H
|
|
DCX H ;CLEARED
|
|
SHLD HLOC ;H,L CLEARED
|
|
PUSH H ;B,C CLEARED
|
|
PUSH H ;D,E CLEARED
|
|
SHLD TRACER ;CLEAR TRACE FLAG
|
|
;
|
|
MVI A,0C3H ;(JMP RESTART)
|
|
STA RSTLOC
|
|
LXI H,BREAKA ;BREAK POINT SUBROUTINE
|
|
SHLD RSTLOC+1 ;RESTART LOCATION ADDRESS FIELD
|
|
;
|
|
; CHECK FOR FILE NAME PASSED TO DEMON, AND LOAD IF PRESENT
|
|
LDA FCB+FFN ;BLANK IF NO NAME PASSED
|
|
CPI ' '
|
|
JZ START
|
|
;
|
|
; PUSH A ZERO, AND READ
|
|
LXI H,0
|
|
PUSH H
|
|
JMP RINIT
|
|
;
|
|
;
|
|
; MAIN COMMAND LOOP
|
|
;
|
|
START:
|
|
LXI SP,STACK-12 ;INITIALIZE SP IN CASE OF ERROR
|
|
; CHECK FOR DISASSEMBLER OVERLOAD
|
|
CALL CHKDIS
|
|
JC DISASMOK
|
|
;
|
|
; DISASSEMBLER NOT PRESENT, SET BDOS JMP
|
|
LXI H,DEMON
|
|
SHLD BDOSE+1 ;(RE)SET JMP ADDRESS
|
|
DISASMOK:
|
|
CALL CRLF ;INITIAL CRLF
|
|
IF DEBUG
|
|
MVI A,':'
|
|
ELSE
|
|
MVI A,'-'
|
|
ENDIF
|
|
CALL PCHAR ;OUTPUT PROMPT
|
|
;
|
|
; GET INPUT BUFFER
|
|
CALL GETBUFF ;FILL COMMAND BUFFER
|
|
;
|
|
CALL GNC ;GET CHARACTER
|
|
CPI CR
|
|
JZ START
|
|
SUI 'A' ;LEGAL CHARACTER?
|
|
JC CERROR ;COMMAND ERROR
|
|
CPI 'Z'-'A'+1
|
|
JNC CERROR
|
|
; CHARACTER IN REGISTER A IS COMMAND, MUST BE IN THE RANGE A-Z
|
|
MOV E,A ;INDEX TO E
|
|
MVI D,0 ;DOUBLE PRECISION INDEX
|
|
LXI H,JMPTAB;BASE OF TABLE
|
|
DAD D
|
|
DAD D ;INDEXED
|
|
MOV E,M ;LO BYTE
|
|
INX H
|
|
MOV D,M ;HO BYTE
|
|
XCHG ;TO H,L
|
|
PCHL ;GONE...
|
|
;
|
|
JMPTAB: ;JUMP TABLE TO SUBROUTINES
|
|
DW ASSM ;A ENTER ASSEMBLER LANGUAGE
|
|
DW CERROR ;B
|
|
DW CERROR ;C
|
|
DW DISPLAY ;D DISPLAY RAM MEMORY
|
|
DW CERROR ;E
|
|
DW FILL ;F FILL MEMORY
|
|
DW GOTO ;G GO TO MEMORY ADDRESS
|
|
DW HEXARI ;H HEXADECIMAL SUM AND DIFFERENCE
|
|
DW INFCB ;I FILL INPUT FILE CONTROL BLOCK
|
|
DW CERROR ;J
|
|
DW CERROR ;K
|
|
DW LASSM ;L LIST ASSEMBLY LANGUAGE
|
|
DW MOVE ;M MOVE MEMORY
|
|
DW CERROR ;N
|
|
DW CERROR ;O
|
|
DW CERROR ;P
|
|
DW CERROR ;Q
|
|
DW READ ;R READ HEXADECIMAL FILE
|
|
DW SETMEM ;S SET MEMORY COMMAND
|
|
DW TRACE ;T
|
|
DW UNTRACE ;U
|
|
DW CERROR ;V
|
|
DW CERROR ;W
|
|
DW EXAMINE ;X EXAMINE AND MODIFY REGISTERS
|
|
DW CERROR ;Y
|
|
DW CERROR ;Z
|
|
;
|
|
;
|
|
OPN: ;FILE OPEN ROUTINE. THIS SUBROUTINE OPENS THE DISK INPUT
|
|
PUSH H
|
|
PUSH D
|
|
PUSH B
|
|
XRA A
|
|
STA DBP ;CLEAR BUFFER POINTER
|
|
MVI C,OPF
|
|
LXI D,DFCB
|
|
CALL TRAPAD ;TO BDS
|
|
POP B
|
|
POP D
|
|
POP H
|
|
RET
|
|
;
|
|
ASSM: ;ASSEMBLER LANGUAGE INPUT
|
|
; CHECK FOR ASSM PRESENT
|
|
CALL CHKDIS ;ASSM/DISASSM PRESENT
|
|
JNC CERROR ;NOT THERE
|
|
;
|
|
CALL SCANEXP ;SCAN THE EXPRESSIONS WHICH FOLLOW
|
|
DCR A ;ONE EXPRESSION EXPECTED
|
|
JNZ CERROR
|
|
CALL GETVAL ;GET EXPRESSION TO H,L
|
|
SHLD DISPC
|
|
CALL ASSEM
|
|
JMP START
|
|
;
|
|
LASSM: ;ASSEMBLER LANGUAGE OUTPUT LISTING
|
|
; L<CR> LISTS FROM CURRENT DISASSM PC FOR SEVERAL LINES
|
|
; L<NUMBER><CR> LISTS FROM <NUMBER> FOR SEVERAL LINES
|
|
; L<NUMBER>,<NUMBER> LISTS BETWEEN LOCATIONS
|
|
CALL CHKDIS ;DISASSM PRESENT?
|
|
JNC CERROR
|
|
;
|
|
CALL SCANEXP ;SCAN EXPRESSIONS WHICH FOLLOW
|
|
JZ SPAGE ;BRANCH IF NOT EXPRESSIONS
|
|
CALL GETVAL ;EXP1 TO H,L
|
|
SHLD DISPC ;SETS BASE PC FOR LIST
|
|
DCR A ;ONLY EXPRESSION?
|
|
JZ SPAGE ;SETS SINGLE PAGE MODE
|
|
;
|
|
; ANOTHER EXPRESSION FOLLOWS
|
|
CALL GETVAL
|
|
SHLD DISPM ;SETS MAX VALUE
|
|
DCR A
|
|
JNZ CERROR ;ERROR IF MORE EXPN'S
|
|
XRA A ;CLEAR PAGE MODE
|
|
JMP SPAG0
|
|
;
|
|
SPAGE: MVI A,PSIZE ;SCREEN SIZE FOR LIST
|
|
SPAG0: STA DISPG
|
|
CALL DISEN ;CALL DISASSEMBLER
|
|
JMP START ;FOR ANOTHER COMMAND
|
|
;
|
|
; DISPLAY MEMORY, FORMS ARE
|
|
; D DISPLAY FROM CURRENT DISPLAY LINE
|
|
; DNNN SET DISPLAY LINE AND ASSUME D
|
|
; DNNN,MMM DISPLAY NNN TO MMM
|
|
; NEW DISPLAY LINE IS SET TO NEXT TO DISPLAY
|
|
;
|
|
DISPLAY:
|
|
CALL SCANEXP ;GET 0,1,OR 2 EXPNS
|
|
JZ DISP1 ;ASSUME CURRENT DISLOC
|
|
CALL GETVAL ;GET VALUE TO H,L
|
|
JC DISP0 ;CARRY SET IF ,B FORM
|
|
SHLD DISLOC ;OTHERWISE DISPC ALREADY SET
|
|
DISP0: ;GET NEXT VALUE
|
|
ANI 7FH ;IN CASE ,B
|
|
DCR A
|
|
JZ DISP1 ;SET HALF PAGE MODE
|
|
CALL GETVAL
|
|
DCR A ;A,B,C NOT ALLOWED
|
|
JNZ CERROR
|
|
JMP DISP2
|
|
;
|
|
DISP1: ;0 OR 1 EXPN, DISPLAY HALF SCREEN
|
|
LHLD DISLOC
|
|
MOV A,L
|
|
ANI 0F0H ;NORMALIZE TO LINE START
|
|
MOV L,A
|
|
LXI D,PSIZE*16-1
|
|
DAD D
|
|
DISP2: SHLD DISMAX
|
|
; DISPLAY MEMORY FROM DISLOC TO DISMAX
|
|
DISP3: CALL CRLF
|
|
CALL BREAK ;BREAK KEY?
|
|
JNZ START ;STOP CURRENT EXPANSION
|
|
LHLD DISLOC
|
|
SHLD TDISP
|
|
CALL PADDR ;PRINT LINE ADDRESS
|
|
DISP4: CALL BLANK
|
|
MOV A,M ;GET NEXT DATA BYTE
|
|
CALL PBYTE ;PRINT BYTE
|
|
INX H
|
|
CALL DISCOM ;COMPARE H,L WITH DISMAX
|
|
JC DISCH ;CARRY SET IF H,L > DISMAX
|
|
MOV A,L ;CHECK FOR LINE OVERFLOW
|
|
ANI 0FH
|
|
JNZ DISP4 ;JUMP FOR ANOTHER BYTE
|
|
;
|
|
DISCH: ;DISPLAY AREA IN CHARACTER FORM
|
|
SHLD DISLOC ;UPDATE FOR NEXT WRITE
|
|
LHLD TDISP
|
|
XCHG
|
|
CALL BLANK
|
|
;
|
|
DISCH0: LDAX D ;GET BYTE
|
|
CALL PGRAPH ;PRINT IF GRAPHIC CHARACTER
|
|
INX D
|
|
LHLD DISLOC ;COMPARE FOR END OF LINE
|
|
MOV A,L
|
|
SUB E
|
|
JNZ DISCH0
|
|
MOV A,H
|
|
SUB D
|
|
JNZ DISCH0
|
|
;
|
|
; DROP THRU AT END OF CHARACTERS
|
|
LHLD DISLOC
|
|
CALL DISCOM ;END OF DISPLAY?
|
|
JC START
|
|
;
|
|
; NO, CONTINUE WITH NEXT LINE
|
|
JMP DISP3
|
|
;
|
|
;
|
|
; FILL MEMORY AREA WITH FIXED DATA ELEMENT
|
|
;
|
|
SCAN3: ;SCAN THREE EXPN'S FOR FILL AND MOVE
|
|
CALL SCANEXP
|
|
CPI 3
|
|
JNZ CERROR
|
|
CALL GETVAL
|
|
PUSH H
|
|
CALL GETVAL
|
|
PUSH H
|
|
CALL GETVAL
|
|
POP D
|
|
POP B ;BC,DE,HL
|
|
RET
|
|
;
|
|
BCDE: ;COMPARE BC > DE (CARRY GEN'D IF TRUE)
|
|
MOV A,E
|
|
SUB C
|
|
MOV A,D
|
|
SBB B
|
|
RET
|
|
;
|
|
FILL:
|
|
CALL SCAN3 ;EXPRESSIONS SCANNED BC , DE , HL
|
|
MOV A,H ;MUST BE ZERO
|
|
ORA A
|
|
JNZ CERROR
|
|
FILL0: CALL BCDE ;END OF FILL?
|
|
JC START
|
|
MOV A,L ;DATA
|
|
STAX B ;TO MEMORY
|
|
INX B ;NEXT TO FILL
|
|
JMP FILL0
|
|
;
|
|
; GO COMMAND WITH OPTIONAL BREAKPOINTS
|
|
;
|
|
GOTO:
|
|
CALL CRLF ;READY FOR GO.
|
|
CALL SCANEXP ;0,1, OR 2 EXPS
|
|
CALL GETVAL
|
|
PUSH H ;START ADDRESS
|
|
CALL GETVAL
|
|
PUSH H ;BKPT1
|
|
CALL GETVAL
|
|
MOV B,H ;BKPT2
|
|
MOV C,L
|
|
POP D ;BKPT1
|
|
POP H ;GOTO ADDRESS
|
|
;
|
|
GOPR:
|
|
DI
|
|
JZ GOP1 ;NO BREAK POINTS
|
|
JC GOP0
|
|
; SET PC
|
|
SHLD PLOC ;INTO MACHINE STATE
|
|
GOP0: ;SET BREAKS
|
|
ANI 7FH ;CLEAR , BIT
|
|
DCR A ;IF 1 THEN SKIP (2,3 IF BREAKPOINTS)
|
|
JZ GOP1
|
|
CALL SETBK ;BREAK POINT FROM D,E
|
|
DCR A
|
|
JZ GOP1
|
|
; SECOND BREAK POINT
|
|
MOV E,C
|
|
MOV D,B ;TO D,E
|
|
CALL SETBK ;SECOND BREAK POINT SET
|
|
;
|
|
GOP1: ;RESTORE MACHINE STATE AND START IT
|
|
LXI SP,STACK-12
|
|
POP D
|
|
POP B
|
|
POP PSW
|
|
POP H ;SP IN HL
|
|
SPHL
|
|
LHLD PLOC ;PC IN HL
|
|
PUSH H ;INTO USER'S STACK
|
|
LHLD HLOC ;HL RESTORED
|
|
EI
|
|
RET
|
|
;
|
|
SETBK: ;SET BREAK POINT AT LOCATION D,E
|
|
PUSH PSW
|
|
PUSH B
|
|
LXI H,BREAKS ;NUMBER OF BREAKS SET SO FAR
|
|
MOV A,M
|
|
INR M ;COUNT BREAKS UP
|
|
ORA A ;ONE SET ALREADY?
|
|
JZ SETBK0
|
|
; ALREADY SET, MOVE PAST ADDR,DATA FIELDS
|
|
INX H
|
|
MOV A,M ;CHECK = ADDRESSES
|
|
INX H
|
|
MOV B,M ;CHECK HO ADDRESS
|
|
INX H
|
|
; DON'T SET TWO BREAKPOINTS IF EQUAL
|
|
CMP E ;LOW =?
|
|
JNZ SETBK0
|
|
MOV A,B
|
|
CMP D ;HIGH =?
|
|
JNZ SETBK0
|
|
; EQUAL ADDRESSES, REPLACE REAL DATA
|
|
MOV A,M ;GET DATA BYTE
|
|
STAX D ;PUT BACK INTO CODE
|
|
SETBK0: INX H ;ADDRESS FIELD
|
|
MOV M,E ;LSB
|
|
INX H
|
|
MOV M,D ;MSB
|
|
INX H ;DATA FIELD
|
|
LDAX D ;GET BYTE FROM PROGRAM
|
|
MOV M,A ;TO BREAKS VECTOR
|
|
MVI A,RSTIN ;RESTART INSTRUCTION
|
|
STAX D ;TO CODE
|
|
POP B
|
|
POP PSW
|
|
RET
|
|
;
|
|
;
|
|
; HEXADECIMAL ARITHMETIC
|
|
;
|
|
HEXARI:
|
|
CALL SCANEXP
|
|
CPI 2
|
|
JNZ CERROR
|
|
CALL GETVAL ;FIRST VALUE TO H,L
|
|
PUSH H
|
|
CALL GETVAL ;SECOND VALUE TO H,L
|
|
POP D ;FIRST VALUE TO D,E
|
|
PUSH H ;SAVE A COPY OF SECOND VAALUE
|
|
CALL CRLF ;NEW LINE
|
|
DAD D ;SUM IN H,L
|
|
CALL PADDR
|
|
CALL BLANK
|
|
POP H ;RESTORE SECOND VALUE
|
|
XRA A ;CLEAR ACCUM FOR SUBTRACTION
|
|
SUB L
|
|
MOV L,A ;BACK TO L
|
|
MVI A,0 ;CLEAR IT AGAIN
|
|
SBB H
|
|
MOV H,A
|
|
DAD D ;DIFFERENCE IN HL
|
|
CALL PADDR
|
|
JMP START
|
|
;
|
|
; SET INPUT FILE CONTROL BLOCK (AT 5CH) TO SIMULATE CONSOLE COMMAND
|
|
INFCB:
|
|
; FILL FCB AT 5CH
|
|
XRA A
|
|
STA FCB+FCR ;CLEAR CURRENT RECORD
|
|
STA FCB ;CLEAR DISK NUMBER
|
|
CALL GNC ;CHARACTER IN A
|
|
MVI C,9 ;FILE NAME LENGTH+1
|
|
LXI H,FCB+FFN ;START OF NAME
|
|
;
|
|
FLP: ;FILL NAME
|
|
MOV M,A
|
|
INX H
|
|
DCR C
|
|
JZ CERROR ;FILE NAME TOO LONG.
|
|
;
|
|
CALL GNC ;READ NEXT CHAR
|
|
CPI '.'
|
|
JZ FLB ;FOUND ., BLANK OUT
|
|
; NOT ., MAY BE CR
|
|
CPI CR
|
|
JNZ FLP ;FOR ANOTHER STORE
|
|
;
|
|
; NAME FILLED, EXTEND WITH BLANKS
|
|
FLB: DCR C
|
|
JZ TFT
|
|
MVI M,' '
|
|
INX H
|
|
JMP FLB
|
|
;
|
|
; BLANKS FILLED, SCAN FILE TYPE IF '.' FOUND
|
|
TFT: MVI C,4
|
|
CPI '.' ;ENDED WITH . OR CR
|
|
JNZ FLB1 ;FILL REMAINDER WITH BLANKS
|
|
;
|
|
; SCAN FILE TYPE
|
|
LXI H,FCB+FFT
|
|
;
|
|
FLP1: CALL GNC
|
|
CPI CR
|
|
JZ FLB1
|
|
MOV M,A
|
|
INX H
|
|
DCR C
|
|
JZ CERROR ;TOO LONG
|
|
JMP FLP1
|
|
;
|
|
; FILL WITH BLANKS
|
|
FLB1: DCR C
|
|
JZ FLZ
|
|
MVI M,' '
|
|
INX H
|
|
JMP FLB1
|
|
;
|
|
; ZERO THE EXTENT
|
|
FLZ: MVI M,0
|
|
JMP START
|
|
;
|
|
; MOVE MEMORY
|
|
MOVE:
|
|
CALL SCAN3 ;BC,DE,HL
|
|
MOVE0: ;HAS B,C PASSED D,E?
|
|
CALL BCDE
|
|
JC START ;END OF MOVE
|
|
LDAX B ;CHAR TO ACCUM
|
|
INX B ;NEXT TO GET
|
|
MOV M,A ;MOVE IT TO MEMORY
|
|
INX H
|
|
JMP MOVE0 ;FOR ANOTHER
|
|
;
|
|
; READ FILES (HEX OR COM)
|
|
;
|
|
QHEX: ;HEX FILE IF ZERO AT END
|
|
LXI H,FCB+FFT
|
|
MOV A,M
|
|
ANI 07FH ;MASK HIGH ORDER BIT
|
|
CPI 'H'
|
|
RNZ
|
|
INX H
|
|
MOV A,M
|
|
ANI 07FH ;MASK HIGH ORDER BIT
|
|
CPI 'E'
|
|
RNZ
|
|
INX H
|
|
MOV A,M
|
|
ANI 07FH ;MASK HIGH ORDER BIT
|
|
CPI 'X'
|
|
RET
|
|
;
|
|
COMLOAD: ;COMPARE HL > MLOAD
|
|
XCHG ;H,L TO D,E
|
|
LHLD MLOAD ;MLOAD TO H,L
|
|
MOV A,L ;MLOAD LSB
|
|
SUB E
|
|
MOV A,H
|
|
SBB D ;MLOAD-OLDHL GENS CARRY IF HL>MLOAD
|
|
XCHG
|
|
RET
|
|
;
|
|
CKMLOAD: ;CHECK FOR HL > MLOAD AND SET MLOAD IF SO
|
|
CALL COMLOAD ;CARRY IF HL>MLOAD
|
|
RNC
|
|
SHLD MLOAD ;CHANGE IT
|
|
RET
|
|
;
|
|
CHKDIS: ;CHECK FOR DISASSM PRESENT
|
|
PUSH H
|
|
LXI H,MODBAS ;ENTRY POINT
|
|
CALL COMLOAD
|
|
POP H
|
|
RET
|
|
;
|
|
READ:
|
|
CALL SCANEXP
|
|
LXI H,0
|
|
JZ READN
|
|
DCR A ;ONE EXPRESSION?
|
|
JNZ CERROR
|
|
CALL GETVAL ;EXPRESSION TO H,L
|
|
READN: PUSH H ;SAVE IT FOR BELOW
|
|
RINIT: CALL OPN ;OPEN INPUT FILE
|
|
CPI 255
|
|
JZ CERROR
|
|
; CONTINUE IF FILE OPEN WENT OK
|
|
; DISK FILE OPENED AND INITIALIZED
|
|
;
|
|
; CHECK FOR 'HEX' FILE AND LOAD DIRECT TIL EOF
|
|
CALL QHEX ;LOOK FOR 'HEX'
|
|
JZ HREAD
|
|
;
|
|
; COM FILE, LOAD WITH OFFSET GIVEN BY PUSHED REGISTER H
|
|
POP H
|
|
LXI D,100H ;BASE OF TRANSIENT AREA
|
|
DAD D
|
|
; REG H HOLDS LOAD ADDRESS
|
|
LCOM0: ;LOAD COM FILE
|
|
PUSH H ;SAVE DMA ADDRESS
|
|
LXI D,DFCB
|
|
MVI C,RDF ;READ SECTOR
|
|
CALL TRAPAD
|
|
POP H
|
|
ORA A ;SET FLAGS TO CHECK RETURN CODE
|
|
JNZ RLIFT
|
|
; MOVE FROM 80H TO LOAD ADDRESS IN H,L
|
|
LXI D,DBF
|
|
MVI C,80H ;BUFFER SIZE
|
|
LCOM1: LDAX D ;LOAD NEXT BYTE
|
|
INX D
|
|
MOV M,A ;STORE NEXT BYTE
|
|
INX H
|
|
DCR C
|
|
JNZ LCOM1
|
|
; LOADED, CHECK ADDRESS AGAINST MLOAD
|
|
CALL CKMLOAD
|
|
JMP LCOM0
|
|
;
|
|
;
|
|
; OTHERWISE ASSUME HEX FILE IS BEING LOADED
|
|
HREAD: CALL DISKR ;NEXT CHAR TO ACCUM
|
|
CPI DEOF ;PAST END OF TAPE?
|
|
JZ CERROR ;FOR ANOTHER COMMAND
|
|
SBI ':'
|
|
JNZ HREAD ;LOOKING FOR START OF RECORD
|
|
;
|
|
; START FOUND, CLEAR CHECKSUM
|
|
MOV D,A
|
|
POP H
|
|
PUSH H
|
|
CALL RBYTE
|
|
MOV E,A ;SAVE LENGTH
|
|
CALL RBYTE ;HIGH ORDER ADDR
|
|
PUSH PSW
|
|
CALL RBYTE ;LOW ORDER ADDR
|
|
POP B
|
|
MOV C,A
|
|
DAD B ;BIASED ADDR IN H
|
|
MOV A,E ;CHECK FOR LAST RECORD
|
|
ORA A
|
|
JNZ RDTYPE
|
|
; END OF TAPE, SET LOAD ADDRESS
|
|
MOV H,B
|
|
MOV L,C
|
|
SHLD PLOC ;SET PC VALUE
|
|
JMP RLIFT ;FOR ANOTHER COMMAND
|
|
;
|
|
RDTYPE:
|
|
CALL RBYTE ;RECORD TYPE = 0
|
|
;
|
|
; LOAD RECORD
|
|
RED1: CALL RBYTE
|
|
MOV M,A
|
|
INX H
|
|
DCR E
|
|
JNZ RED1 ;FOR ANOTHER BYTE
|
|
; OTHERWISE AT END OF RECORD - CHECKSUM
|
|
CALL RBYTE
|
|
PUSH PSW ;FOR CHECKSUM CHECK
|
|
CALL CKMLOAD ;CHECK AGAINST MLOAD
|
|
POP PSW
|
|
JNZ CERROR ;CHECKSUM ERROR
|
|
JMP HREAD ;FOR ANOTHER RECORD
|
|
;
|
|
RBYTE: ;READ ONE BYTE FROM BUFF AT WBP TO REG-A
|
|
; COMPUTE CHECKSUM IN REG-D
|
|
PUSH B
|
|
PUSH H
|
|
PUSH D
|
|
;
|
|
CALL DISKR ;GET ONE MORE CHARACTER
|
|
CALL HEXCON ;CONVERT TO HEX (OR ERROR)
|
|
;
|
|
; SHIFT LEFT AND MASK
|
|
RLC
|
|
RLC
|
|
RLC
|
|
RLC
|
|
ANI 0F0H
|
|
PUSH PSW ;SAVE FOR A FEW STEPS
|
|
CALL DISKR
|
|
CALL HEXCON
|
|
;
|
|
; OTHERWISE SECOND NIBBLE OK, SO MERGE
|
|
POP B ;PREVIOUS NIBBLE TO REG-B
|
|
ORA B
|
|
MOV B,A ;VALUE IS NOW IN B TEMPORARILY
|
|
POP D ;CHECKSUM
|
|
ADD D ;ACCUMULATING
|
|
MOV D,A ;BACK TO CS
|
|
; ZERO FLAG REMAINS SET
|
|
MOV A,B ;BRING BYTE BACK TO ACCUMULATOR
|
|
POP H
|
|
POP B ;BACK TO INITIAL STATE WITH ACCUM SET
|
|
RET
|
|
RLIFT: ;LIFT HEAD ON DISK BEFORE RETURNING
|
|
MVI C,LIFT
|
|
CALL TRAPAD
|
|
; 'NEXT' ' PC'
|
|
LXI H,LMSG ;LOAD MESSAGE
|
|
RLI0: MOV A,M
|
|
ORA A ;LAST CHAR?
|
|
JZ RLI1
|
|
CALL PCHAR
|
|
INX H ;NEXT CHAR
|
|
JMP RLI0
|
|
RLI1: CALL CRLF
|
|
LHLD MLOAD
|
|
CALL PADDR
|
|
CALL BLANK
|
|
LHLD PLOC
|
|
CALL PADDR
|
|
JMP START
|
|
LMSG: DB CR,LF,'NEXT PC',0
|
|
;
|
|
; SET MEMORY COMMAND
|
|
;
|
|
SETMEM: ;ONE EXPRESSION EXPECTED
|
|
CALL SCANEXP ;SETS FLAGS
|
|
DCR A ;ONE EXPRESSION ONLY
|
|
JNZ CERROR
|
|
CALL GETVAL ;START ADDRESS IS IN H,L
|
|
SETM0: CALL CRLF ;NEW LINE
|
|
PUSH H ;SAVE CURRENT ADDRESS
|
|
CALL PADDR ;PRINTED
|
|
CALL BLANK ;SEPARATOR
|
|
POP H ;GET DATA
|
|
MOV A,M
|
|
PUSH H ;SAVE ADDRESS TO FILL
|
|
CALL PBYTE ;PRINT BYTE
|
|
CALL BLANK ;ANOTHER SEPARATOR
|
|
CALL GETBUFF ;FILL INPUT BUFFER
|
|
CALL GNC ;MAY BE EMPTY (NO CHANGE)
|
|
POP H ;RESTORE ADDRESS TO FILL
|
|
CPI CR
|
|
JZ SETM1
|
|
CPI '.'
|
|
JZ START
|
|
; DATA IS BEING CHANGED
|
|
PUSH H ;SAVE ADDR TO FILL
|
|
CALL SCANEX ;FIRST CHARACTER ALREADY SCANNED
|
|
DCR A ;ONE ITEM?
|
|
JNZ CERROR ;MORE THAN ONE
|
|
CALL GETVAL ;VALUE TO H,L
|
|
MOV A,H
|
|
ORA A ;HO ZERO?
|
|
JNZ CERROR ;DATA IS IN L
|
|
MOV A,L
|
|
POP H ;RESTORE DATA VALUE
|
|
MOV M,A
|
|
SETM1: INX H ;NEXT ADDRESS READY
|
|
JMP SETM0
|
|
;
|
|
; UNTRACE MODE
|
|
UNTRACE:
|
|
XRA A ;CLEAR TRACE MODE FLAG
|
|
JMP ETRACE
|
|
;
|
|
; START TRACE
|
|
TRACE: MVI A,0FFH ;SET TRACE MODE FLAG
|
|
ETRACE:
|
|
STA TMODE
|
|
CALL SCANEXP
|
|
LXI H,0
|
|
JZ TRAC0
|
|
; MUST BE T OR TN (N NOT 0)
|
|
DCR A ;COUNT MUST BE ONE
|
|
JNZ CERROR
|
|
CALL GETVAL ;GET VALUE TO HL
|
|
MOV A,L ;CHECK FOR ZERO
|
|
ORA H
|
|
JZ CERROR
|
|
DCX H ;TRACE VALUE - 1
|
|
TRAC0: SHLD TRACER
|
|
CALL DSTATE ;STARTING STATE IS DISPLAYED
|
|
JMP GOPR ;SETS BREAKPOINTS AND STARTS EXECUTION
|
|
;
|
|
; EXAMINE AND MODIFY CPU REGISTERS.
|
|
EXAMINE:
|
|
CALL GNC ;CR?
|
|
CPI CR
|
|
JNZ EXAM0
|
|
CALL DSTATE ;DISPLAY CPU STATE
|
|
JMP START
|
|
;
|
|
EXAM0: ;REGISTER CHANGE OPERATION
|
|
LXI B,PVAL+1 ;B=0,C=PVAL (MAX REGISTER NUMBER)
|
|
; LOOK FOR REGISTER MATCH IN RVECT
|
|
LXI H,RVECT
|
|
EXAM1: CMP M ;MATCH IN RVECT?
|
|
JZ EXAM2
|
|
INX H ;NEXT RVECT
|
|
INR B ;INCREMENT COUNT
|
|
DCR C ;END OF RVECT?
|
|
JNZ EXAM1
|
|
; NO MATCH
|
|
JMP CERROR
|
|
;
|
|
EXAM2: ;MATCH IN RVECT, B HAS REGISTER NUMBER
|
|
CALL GNC
|
|
CPI CR ;ONLY CHARACTER?
|
|
JNZ CERROR
|
|
;
|
|
; WRITE CONTENTS, AND GET ANOTHER BUFFER
|
|
PUSH B ;SAVE COUNT
|
|
CALL CRLF ;NEW LINE FOR ELEMENT
|
|
CALL DELT ;ELEMENT WRITTEN
|
|
CALL BLANK
|
|
CALL GETBUFF ;FILL COMMAND BUFFER
|
|
CALL SCANEXP ;GET INPUT EXPRESSION
|
|
ORA A ;NONE?
|
|
JZ START
|
|
DCR A ;MUST BE ONLY ONE
|
|
JNZ CERROR
|
|
CALL GETVAL ;VALUE IS IN H,L
|
|
POP B ;RECALL REGISTER NUMBER
|
|
; CHECK CASES FOR FLAGS, REG-A, OR DOUBLE REGISTER
|
|
MOV A,B
|
|
CPI AVAL
|
|
JNC EXAM4
|
|
; SETTING FLAGS, MUST BE ZERO OR ONE
|
|
MOV A,H
|
|
ORA A
|
|
JNZ CERROR
|
|
MOV A,L
|
|
CPI 2
|
|
JNC CERROR
|
|
; 0 OR 1 IN H,L REGISTERS - GET CURRENT FLAGS AND MASK POSITION
|
|
CALL FLGSHF
|
|
; SHIFT COUNT IN C, D,E ADDRESS FLAG POSITION
|
|
MOV H,A ;FLAGS TO H
|
|
MOV B,C ;SHIFT COUNT TO B
|
|
MVI A,0FEH ;111111110 IN ACCUM TO ROTATE
|
|
CALL LROTATE ;ROTATE REG-A LEFT
|
|
ANA H ;MASK ALL BUT ALTERED BIT
|
|
MOV B,C ;RESTORE SHIFT COUNT TO B
|
|
MOV H,A ;SAVE MASKED FLAGS
|
|
MOV A,L ;0/1 TO LSB OF ACCUM
|
|
CALL LROTATE ;ROTATED TO CHANGED POSITION
|
|
ORA H ;RESTORE ALL OTHER FLAGS
|
|
STAX D ;BACK TO MACHINE STATE
|
|
JMP START ;FOR ANOTHER COMMAND
|
|
;
|
|
LROTATE: ;LEFT ROTATE FOR FLAG SETTING
|
|
; PATTERN IS IN REGISTER A, COUNT IN REGISTER B
|
|
DCR B
|
|
RZ ;ROTATE COMPLETE
|
|
RLC ;END-AROUND ROTATE
|
|
JMP LROTATE
|
|
;
|
|
EXAM4: ;MAY BE ACCUMULATOR CHANGE
|
|
JNZ EXAM5
|
|
; MUST BE BYTE VALUE
|
|
MOV A,H
|
|
ORA A
|
|
JNZ CERROR
|
|
MOV A,L ;GET BYTE TO STORE
|
|
LXI H,ALOC ;A REG LOCATION IN MACHINE STATE
|
|
MOV M,A ;STORE IT AWAY
|
|
JMP START
|
|
;
|
|
EXAM5: ;MUST BE DOUBLE REGISTER PAIR
|
|
PUSH H ;SAVE VALUE
|
|
CALL GETDBA ;DOUBLE ADDRESS TO HL
|
|
POP D ;VALUE TO D,E
|
|
MOV M,E
|
|
INX H
|
|
MOV M,D ;ALTERED MACHINE STATE
|
|
JMP START
|
|
;
|
|
DISKR: ;DISK READ
|
|
PUSH H
|
|
PUSH D
|
|
PUSH B
|
|
;
|
|
RDI: ;READ DISK INPUT
|
|
LDA DBP
|
|
ANI 7FH
|
|
JZ NDI ;GET NEXT DISK INPUT RECORD
|
|
;
|
|
; READ CHARACTER
|
|
RDC:
|
|
MVI D,0
|
|
MOV E,A
|
|
LXI H,DBF
|
|
DAD D
|
|
MOV A,M
|
|
CPI DEOF
|
|
JZ DEF ;END OF FILE
|
|
LXI H,DBP
|
|
INR M
|
|
ORA A
|
|
JMP RRET
|
|
;
|
|
NDI: ;NEXT BUFFER IN
|
|
MVI C,RDF
|
|
LXI D,DFCB
|
|
CALL TRAPAD
|
|
ORA A
|
|
JNZ DEF
|
|
;
|
|
; BUFFER READ OK
|
|
STA DBP ;STORE 00H
|
|
JMP RDC
|
|
;
|
|
DEF: ;SET CARRY AND RETURN (END FILE)
|
|
STC
|
|
RRET:
|
|
POP B
|
|
POP D
|
|
POP H
|
|
RET
|
|
;
|
|
CERROR: ;ERROR IN COMMAND
|
|
CALL CRLF
|
|
MVI A,'?'
|
|
CALL PCHAR
|
|
JMP START
|
|
;
|
|
; SUBROUTINES
|
|
GETBUFF: ;FILL COMMAND BUFFER AND SET POINTERS
|
|
MVI C,GETF ;GET BUFFER FUNCTION
|
|
LXI D,COMLEN;START OF COMMAND BUFFER
|
|
CALL TRAPAD ;FILL BUFFER
|
|
LXI H,COMBUF;NEXT TO GET
|
|
SHLD NEXTCOM
|
|
RET
|
|
;
|
|
BLANK:
|
|
MVI A,' '
|
|
;
|
|
PCHAR: ;PRINT CHARACTER TO CONSOLE
|
|
PUSH H
|
|
PUSH D
|
|
PUSH B
|
|
MOV E,A
|
|
MVI C,COF
|
|
CALL TRAPAD
|
|
POP B
|
|
POP D
|
|
POP H
|
|
RET
|
|
;
|
|
TRANS:
|
|
; TRANSLATE TO UPPER CASE
|
|
CPI 7FH ;RUBOUT?
|
|
RZ
|
|
CPI ('A' OR 0100000B) ;UPPER CASE A
|
|
RC
|
|
ANI 1011111B ;CLEAR UPPER CASE BIT
|
|
RET
|
|
;
|
|
GNC:
|
|
; GET NEXT BUFFER CHARACTER FROM CONSOLE
|
|
PUSH H ;SAVE FOR REUSE LOCALLY
|
|
LXI H,CURLEN
|
|
MOV A,M
|
|
ORA A ;ZERO?
|
|
MVI A,CR
|
|
JZ GNCRET ;RETURN WITH CR IF EXHAUSTED
|
|
DCR M ;CURLEN=CURLEN-1
|
|
LHLD NEXTCOM
|
|
MOV A,M ;GET NEXT CHARACTER
|
|
INX H ;NEXTCOM=NEXTCOM+1
|
|
SHLD NEXTCOM ;UPDATED
|
|
CALL TRANS
|
|
GNCRET: POP H ;RESTORE ENVIRONMENT
|
|
RET
|
|
;
|
|
PNIB: ;PRINT NIBBLE IN LO ACCUM
|
|
CPI 10
|
|
JNC PNIBH ;JUMP IF A-F
|
|
ADI '0'
|
|
JMP PCHAR ;RET THRU PCHAR
|
|
PNIBH: ADI 'A'-10
|
|
JMP PCHAR
|
|
;
|
|
PBYTE: PUSH PSW ;SAVE A COPY FOR LO NIBBLE
|
|
RAR
|
|
RAR
|
|
RAR
|
|
RAR
|
|
ANI 0FH ;MASK HO NIBBLE TO LO NIBBLE
|
|
CALL PNIB
|
|
POP PSW ;RECALL BYTE
|
|
ANI 0FH
|
|
JMP PNIB
|
|
;
|
|
CRLF: ;CARRIAGE RETURN LINE FEED
|
|
MVI A,CR
|
|
CALL PCHAR
|
|
MVI A,LF
|
|
JMP PCHAR
|
|
;
|
|
BREAK: ;CHECK FOR BREAK KEY
|
|
PUSH B
|
|
PUSH D
|
|
PUSH H
|
|
MVI C,CHKIO
|
|
CALL TRAPAD
|
|
ANI 1B
|
|
POP H
|
|
POP D
|
|
POP B
|
|
RET
|
|
;
|
|
PADDX: ;SAME AS PADDR, EXCEPT PRINT VALUE IN D,E
|
|
XCHG
|
|
;
|
|
PADDR: ;PRINT THE ADDRESS VALUE IN H,L
|
|
MOV A,H
|
|
CALL PBYTE
|
|
MOV A,L
|
|
JMP PBYTE
|
|
;
|
|
PGRAPH: ;PRINT GRAPHIC CHARACTER IN REG-A OR '.' IF NOT
|
|
CPI 7FH
|
|
JNC PPERIOD
|
|
CPI ' '
|
|
JNC PCHAR
|
|
PPERIOD:
|
|
MVI A,'.'
|
|
JMP PCHAR
|
|
;
|
|
DISCOM: ;COMPARE H,L AGAINST DISMAX. CARRY SET IF HL > DISMAX AND
|
|
XCHG
|
|
LHLD DISMAX
|
|
MOV A,L
|
|
SUB E
|
|
MOV L,A ;REPLACE FOR ZERO TESTS LATER
|
|
MOV A,H
|
|
SBB D
|
|
XCHG
|
|
RET
|
|
;
|
|
DELIM: ;CHECK FOR DELIMITER CHARACTER
|
|
CPI CR
|
|
RZ
|
|
CPI ','
|
|
RZ
|
|
CPI ' '
|
|
RET
|
|
;
|
|
HEXCON: ;CONVERT ACCUMULATOR TO PURE BINARY FROM EXTERNAL HEX
|
|
SUI '0'
|
|
CPI 10
|
|
RC ;MUST BE 0-9
|
|
ADI ('0'-'A'+10) AND 0FFH
|
|
CPI 16
|
|
RC ;MUST BE 0-15
|
|
JMP CERROR ;BAD HEX DIGIT
|
|
;
|
|
GETVAL: ;GET NEXT EXPRESSION VALUE TO H,L (POINTER IN D,E ASSUMED)
|
|
XCHG
|
|
MOV E,M
|
|
INX H
|
|
MOV D,M
|
|
INX H
|
|
XCHG
|
|
RET
|
|
;
|
|
GETEXP: ;GET HEX VALUE TO D,E
|
|
XCHG
|
|
LXI H,0
|
|
GETEXP0:
|
|
CALL HEXCON
|
|
DAD H ;*2
|
|
DAD H ;*4
|
|
DAD H ;*8
|
|
DAD H ;*16
|
|
ORA L ;HL=HL+HEX
|
|
MOV L,A
|
|
CALL GNC
|
|
CALL DELIM ;DELIMITER?
|
|
JNZ GETEXP0
|
|
XCHG
|
|
RET
|
|
;
|
|
SCSTORE: ;STORE D,E TO H,L AND INCREMENT ADDRESS
|
|
MOV M,E
|
|
INX H
|
|
MOV M,D
|
|
INX H
|
|
PUSH H
|
|
LXI H,EXPLIST
|
|
INR M ;COUNT NUMBER OF EXPN'S
|
|
POP H
|
|
RET
|
|
;
|
|
SCANEXP: ;SCAN EXPRESSIONS - CARRY SET IF ,B
|
|
; ZERO SET IF NO EXPRESSIONS, A SET TO NUMBER OF EXPRESSIONS
|
|
; HI ORDER BIT SET IF ,B ALSO
|
|
CALL GNC
|
|
SCANEX: ;ENTER HERE IF CHARACTER ALREADY SCANNED
|
|
LXI H,EXPLIST
|
|
MVI M,0 ;ZERO EXPRESSIONS
|
|
INX H ;READY TO FILL EXPRESSION LIST
|
|
CPI CR ;END OF LINE?
|
|
JZ SCANRET
|
|
;
|
|
; NOT CR, MUST BE DIGIT OR COMMA
|
|
CPI ','
|
|
JNZ SCANE0
|
|
; MARK AS COMMA
|
|
MVI A,80H
|
|
STA EXPLIST
|
|
LXI D,0
|
|
JMP SCANE1
|
|
;
|
|
SCANE0: ;NOT CR OR COMMA
|
|
CALL GETEXP ;EXPRESSION TO D,E
|
|
SCANE1: CALL SCSTORE ;STORE THE EXPRESSION AND INCREMENT H,L
|
|
CPI CR
|
|
JZ SCANRET
|
|
CALL GNC
|
|
CALL GETEXP
|
|
CALL SCSTORE
|
|
; SECOND DIGIT SCANNED
|
|
CPI CR
|
|
JZ SCANRET
|
|
CALL GNC
|
|
CALL GETEXP
|
|
CALL SCSTORE
|
|
CPI CR
|
|
JNZ CERROR
|
|
SCANRET:
|
|
LXI D,EXPLIST ;LOOK AT COUNT
|
|
LDAX D ;LOAD COUNT TO ACC
|
|
CPI 81H ;, WITHOUT B?
|
|
JZ CERROR
|
|
INX D ;READY TO EXTRACT EXPN'S
|
|
ORA A ;ZERO FLAG MAY BE SET
|
|
RLC
|
|
RRC ;SET CARRY IF HO BIT SET (,B)
|
|
RET ;WITH FLAGS SET
|
|
;
|
|
;
|
|
; SUBROUTINES FOR CPU STATE DISPLAY
|
|
FLGSHF: ;SHIFT COMPUTATION FOR FLAG GIVEN BY REG-B
|
|
; REG A CONTAINS FLAG UPON EXIT (UNSHIFTED)
|
|
; REG C CONTAINS NUMBER OF SHIFTS REQUIRED+1
|
|
; REGS D,E CONTAIN ADDRESS OF FLAGS IN TEMPLATE
|
|
PUSH H
|
|
LXI H,FLGTAB ;SHIFT TABLE
|
|
MOV E,B
|
|
MVI D,0
|
|
DAD D
|
|
MOV C,M ;SHIFT COUNT TO C
|
|
LXI H,FLOC ;ADDRESS OF FLAGS
|
|
MOV A,M ;TO REG A
|
|
XCHG ;SAVE ADDRESS
|
|
POP H
|
|
RET
|
|
;
|
|
GETFLG: ;GET FLAG GIVEN BY REG-B TO REG-A AND MASK
|
|
CALL FLGSHF ;BITS TO SHIFT IN REG-A
|
|
GETFL0: DCR C
|
|
JZ GETFL1
|
|
RAR
|
|
JMP GETFL0
|
|
GETFL1: ANI 1B
|
|
RET
|
|
;
|
|
GETDBA: ;GET DOUBLE BYTE ADDRESS CORRESPONDING TO REG-A TO HL
|
|
SUI BVAL ;NORMALIZE TO 0,1,...
|
|
LXI H,RINX ;INDEX TO STACKED VALUES
|
|
MOV E,A ;INDEX TO E
|
|
MVI D,0 ;DOUBLE PRECISION
|
|
DAD D ;INDEXED INTO VECTOR
|
|
MOV E,M ;OFFSET TO E
|
|
MVI D,0FFH ;-1
|
|
LXI H,STACK
|
|
DAD D ;HL HAS BASE ADDRESS
|
|
RET
|
|
;
|
|
GETDBL: ;GET DOUBLE BYTE CORRESPONDING TO REG-A TO HL
|
|
CALL GETDBA ;ADDRESS OF ELT IN HL
|
|
MOV E,M ;LSB
|
|
INX H
|
|
MOV D,M ;MSB
|
|
XCHG ;BACK TO HL
|
|
RET
|
|
;
|
|
DELT: ;DISPLAY CPU ELEMENT GIVEN BY COUNT IN REG-B, ADDRESS IN H,L
|
|
MOV A,M ;GET CHARACTER
|
|
CALL PCHAR ;PRINT IT
|
|
MOV A,B ;GET COUNT
|
|
CPI AVAL ;PAST A?
|
|
JNC DELT0 ;JMP IF NOT FLAG
|
|
;
|
|
; DISPLAY FLAG
|
|
CALL GETFLG ;FLAG TO REG-A
|
|
CALL PNIB
|
|
RET
|
|
;
|
|
DELT0: ;NOT FLAG, DISPLAY = AND DATA
|
|
PUSH PSW
|
|
MVI A,'='
|
|
CALL PCHAR
|
|
POP PSW
|
|
JNZ DELT1 ;JUMP IF NOT REG-A
|
|
;
|
|
; REGISTER A, DISPLAY BYTE VALUE
|
|
LXI H,ALOC
|
|
MOV A,M
|
|
CALL PBYTE
|
|
RET
|
|
;
|
|
DELT1: ;DOUBLE BYTE DISPLAY
|
|
CALL GETDBL ;TO H,L
|
|
CALL PADDR ;PRINTED
|
|
RET
|
|
;
|
|
DSTATE: ;DISPLAY CPU STATE
|
|
LXI H,RVECT ;REGISTER VECTOR
|
|
MVI B,0 ;REGISTER COUNT
|
|
CALL CRLF
|
|
DSTA0: PUSH B
|
|
PUSH H
|
|
CALL DELT ;ELEMENT DISPLAYED
|
|
POP H ;RVECT ADDRESS RESTORED
|
|
POP B ;COUNT RESTORED
|
|
INR B ;NEXT COUNT
|
|
INX H ;NEXT REGISTER
|
|
MOV A,B ;LAST COUNT?
|
|
CPI PVAL+1
|
|
JNC DSTA1 ;JMP IF PAST END
|
|
CPI AVAL ;BLANK AFTER?
|
|
JC DSTA0
|
|
; YES, BLANK AND GO AGAIN
|
|
CALL BLANK
|
|
JMP DSTA0
|
|
;
|
|
; READY TO SEND DECODED INSTRUCTION
|
|
DSTA1:
|
|
CALL BLANK
|
|
CALL NBRK ;COMPUTE BREAKPOINTS IN CASE OF TRACE
|
|
PUSH PSW ;SAVE EXPRESSION COUNT - B,C AND D,E HAVE BPTS
|
|
PUSH D ;SAVE BP ADDRESS
|
|
PUSH B ;SAVE AUX BREAKPOINT
|
|
CALL CHKDIS ;CHECK TO SEE IF DISASSEMBER IS HERE
|
|
JNC DCHEX ;DISPLAY HEX IF NOT
|
|
; DISASSEMBLE CODE
|
|
LHLD PLOC ;GET CURRENT PC
|
|
SHLD DISPC ;SET DISASSM PC
|
|
LXI H,DISPG;PAGE MODE = 0FFH TO TRACE
|
|
MVI M,0FFH
|
|
CALL DISEN
|
|
JMP DSTRET
|
|
;
|
|
DCHEX: ;DISPLAY HEX
|
|
DCX H ;POINT TO LAST TO WRITE
|
|
SHLD DISMAX ;SAVE FOR COMPARE BELOW
|
|
LHLD PLOC ;START ADDRESS OF TRACE
|
|
MOV A,M ;GET OPCODE
|
|
CALL PBYTE
|
|
INX H ;READY FOR NEXT BYTE
|
|
CALL DISCOM ;ZERO SET IF ONE BYTE TO PRINT, CARRY IF NO MORE
|
|
JC DSTRET
|
|
PUSH PSW ;SAVE RESULT OF ZERO TEST
|
|
CALL BLANK ;SEPARATOR
|
|
POP PSW ;RECALL ZERO TEST
|
|
ORA E ;ZERO TEST
|
|
JZ DSTA2
|
|
; DISPLAY DOUBLE BYTE
|
|
MOV E,M
|
|
INX H
|
|
MOV D,M
|
|
XCHG
|
|
CALL PADDR ;PRINT ADDRESS
|
|
JMP DSTRET
|
|
;
|
|
DSTA2: ;PRINT BYTE VALUE
|
|
MOV A,M
|
|
CALL PBYTE
|
|
DSTRET:
|
|
POP B ;AUX BREAKPOINT
|
|
POP D ;RESTORE BREAKPOINT
|
|
POP PSW ;RESTORE COUNT
|
|
RET
|
|
;
|
|
; DATA VECTORS FOR CPU DISPLAY
|
|
RVECT: DB 'CZMEIABDHSP'
|
|
RINX: DB (BLOC-STACK) AND 0FFH ;LOCATION OF BC
|
|
DB (DLOC-STACK) AND 0FFH ;LOCATION OF DE
|
|
DB (HLOC-STACK) AND 0FFH ;LOCATION OF HL
|
|
DB (SLOC-STACK) AND 0FFH ;LOCATION OF SP
|
|
DB (PLOC-STACK) AND 0FFH ;LOCATION OF PC
|
|
; FLGTAB ELEMENTS DETERMINE SHIFT COUNT TO SET/EXTRACT FLAGS
|
|
FLGTAB: DB 1,7,8,3,5 ;CY, ZER, SIGN, PAR, IDCY
|
|
;
|
|
CLRTRACE: ;CLEAR THE TRACE FLAG
|
|
LXI H,0
|
|
SHLD TRACER
|
|
RET
|
|
;
|
|
BREAKP: ;ARRIVE HERE WHEN PROGRAMMED BREAK OCCURS
|
|
DI
|
|
SHLD HLOC ;HL SAVED
|
|
POP H ;RECALL RETURN ADDRESS
|
|
DCX H ;DECREMENT FOR RESTART
|
|
SHLD PLOC
|
|
; DAD SP BELOW DESTROYS CY, SO SAVE AND RECALL
|
|
PUSH PSW ;INTO USER'S STACK
|
|
LXI H,2 ;BIAS SP BY 2 BECAUSE OF PUSH
|
|
DAD SP ;SP IN HL
|
|
POP PSW ;RESTORE CY AND FLAGS
|
|
LXI SP,STACK-4;LOCAL STACK
|
|
PUSH H ;SP SAVED
|
|
PUSH PSW
|
|
PUSH B
|
|
PUSH D
|
|
; MACHINE STATE SAVED, CLEAR BREAK POINTS
|
|
LHLD PLOC ;CHECK FOR RST INSTRUCTION
|
|
MOV A,M ;OPCODE TO A
|
|
CPI RSTIN
|
|
; SAVE CONDITION CODES FOR LATER TEST
|
|
PUSH PSW
|
|
; SAVE PLOC FOR LATER INCREMENT OR DECREMENT
|
|
PUSH H
|
|
;
|
|
; CLEAR BREAKPOINTS WHICH ARE PENDING
|
|
LXI H,BREAKS
|
|
MOV A,M
|
|
MVI M,0 ;SET TO ZERO BREAKS
|
|
CLER0: ORA A ;ANY MORE?
|
|
JZ CLER1
|
|
DCR A
|
|
MOV B,A ;SAVE COUNT
|
|
INX H ;ADDRESS OF BREAK
|
|
MOV E,M ;LOW ADDR
|
|
INX H
|
|
MOV D,M ;HIGH ADDR
|
|
INX H
|
|
MOV A,M ;INSTRUCTION
|
|
STAX D ;BACK TO PROGRAM
|
|
MOV A,B ;RESTORE COUNT
|
|
JMP CLER0
|
|
;
|
|
CLER1: ;CLEARED, CONTINUE TRACING, OR STOP EXECUTION
|
|
POP H ;RESTORE PLOC
|
|
POP PSW ;RESTORE CONDITION FLAGS
|
|
JZ BREAK0 ;BRANCH IF PROGRAMMED INTERRUPT
|
|
;
|
|
; MUST BE FRONT PANEL INTERRUPT, CHECK IF IN BDOS
|
|
INX H ;DON'T DECREMENT ON PANEL INTERRUPT
|
|
SHLD PLOC ;RESTORE TO NEXT LOGICAL INSTRUCTION
|
|
XCHG ;TO D,E FOR COMPARE
|
|
LXI H,TRAPJMP+1
|
|
MOV C,M ;LOW BDOS ADDR
|
|
INX H
|
|
MOV B,M ;HIGH BDOS ADDR
|
|
CALL BCDE ;CY IF BDOS>PLOC
|
|
JC BREAK0 ;BRANCH IF PLOC <= BDOS
|
|
;
|
|
; IN THE BDOS, DON'T BREAK UNTIL THE RETURN OCCURS
|
|
CALL CLRTRACE;CLEAR TRACE FLAGS
|
|
LHLD RETLOC ;TRAPPED RETLOC ON ENTRY TO DOS
|
|
XCHG ;TO D,E READY FOR BREAKPOINT
|
|
MVI A,82H ;LOOKS LIKE G,BBBB
|
|
ORA A ;SETS FLAGS
|
|
STC ;SUBSEQUENT TEST FOR CY
|
|
JMP GOPR ;START PROGRAM EXECUTION, WITH BREAKPOINT
|
|
;
|
|
BREAK0: ;NORMAL BREAKPOINT
|
|
EI
|
|
LHLD TRACER
|
|
MOV A,H
|
|
ORA L
|
|
JZ STOPEX
|
|
;
|
|
; TRACE IS ON
|
|
DCX H
|
|
SHLD TRACER
|
|
CALL BREAK ;BREAK KEY DEPRESSED?
|
|
JNZ STOPEX
|
|
LDA TMODE ;TRACE MODE T IF 0FFH
|
|
ORA A
|
|
JNZ BREAK1
|
|
; NOT TRACING, BUT MONITORING, SO SET BREAKPOINTS
|
|
CALL NBRK
|
|
JMP GOPR
|
|
;
|
|
BREAK1: ;TRACING AND MONITORING
|
|
CALL DSTATE ;STATE DISPLAYED, CHECK FOR BREAKPOINTS
|
|
JMP GOPR ;STARTS EXECUTION
|
|
;
|
|
STOPEX:
|
|
CALL CLRTRACE ;TRACE FLAGS GO TO ZERO
|
|
MVI A,'*'
|
|
CALL PCHAR
|
|
LHLD PLOC
|
|
; CHECK TO ENSURE DISASSEMBLER IS PRESENT
|
|
CALL CHKDIS
|
|
JNC STOP0
|
|
SHLD DISPC
|
|
STOP0: CALL PADDR
|
|
LHLD HLOC
|
|
SHLD DISLOC
|
|
JMP START
|
|
;
|
|
CAT: ;DETERMINE OPCODE CATEGORY - CODE IN REGISTER B
|
|
; D,E CONTAIN DOUBLE PRECISION CATEGORY NUMBER ON RETURN
|
|
LXI D,OPMAX ;D=0,E=OPMAX
|
|
LXI H,OPLIST
|
|
CAT0: MOV A,M ;MASK TO A
|
|
ANA B ;MASK OPCODE FROM B
|
|
INX H ;READY FOR COMPARE
|
|
CMP M ;SAME AFTER MASK?
|
|
INX H ;READY FOR NEXT COMPARE
|
|
JZ CAT1 ;EXIT IF COMPARED OK
|
|
INR D ;UP COUNT IF NOT MATCHED
|
|
DCR E ;FINISHED?
|
|
JNZ CAT0
|
|
CAT1: MOV E,D ;E IS CATEGORY NUMBER
|
|
MVI D,0 ;DOUBLE PRECISION
|
|
RET
|
|
;
|
|
NBRK: ;FIND NEXT BREAK POINT ADDRESS
|
|
; UPON RETURN, REGISTER A IS SETUP AS IF USER TYPED G,B1,B2 OR
|
|
; G,B1 DEPENDING UPON OPERATOR CATEGORY. B,C CONTAINS SECOND BP,
|
|
; D,E CONTAINS PRIMARY BP. HL ADDRESS NEXT OPCODE BYTE
|
|
LHLD PLOC
|
|
MOV B,M ;GET OPERATOR
|
|
INX H ;HL ADDRESS BYTE FOLLOWING OPCODE
|
|
PUSH H ;SAVE IT FOR LATER
|
|
CALL CAT ;DETERMINE OPERATOR CATEGORY
|
|
LXI H,CATNO ;SAVE CATEGORY NUMBER
|
|
MOV M,E
|
|
LXI H,CATTAB;CATEGORY TABLE BASE
|
|
DAD D ;INXED
|
|
DAD D ;INXED*2
|
|
MOV E,M ;LOW BYTE TO E
|
|
INX H
|
|
MOV D,M ;HIGH BYTE TO D
|
|
XCHG
|
|
PCHL ;JUMP INTO TABLE
|
|
CATTAB: DW JMPOP ;JUMP OPERATOR
|
|
DW CCOP ;JUMP CONDITIONAL
|
|
DW JMPOP ;CALL OPERATOR (TREATED AS JMP)
|
|
DW CCOP ;CALL CONDITIONAL
|
|
DW RETOP ;RETURN FROM SUBROUTINE
|
|
DW RSTOP ;RESTART
|
|
DW PCOP ;PCHL
|
|
DW IMOP ;SINGLE PRECISION IMMEDIATE (2 BYTE)
|
|
DW IMOP ;ADI ... CPI
|
|
DW DIMOP ;DOUBLE PRECISION IMMEDIATE (3 BYTES)
|
|
DW DIMOP ;LHLD ... STA
|
|
DW RCOND ;RETURN CONDITIONAL
|
|
DW IMOP ;IN/OUT
|
|
; NEXT DW MUST BE THE LAST IN THE SEQUENCE
|
|
DW SIMOP ;SIMPLE OPERATOR (1 BYTE)
|
|
;
|
|
JMPOP: ;GET OPERAND FIELD, CHECK FOR BDOS
|
|
CALL GETOPA ;GET OPERAND ADDRESS TO D,E AND COMPARE WITH BDOS
|
|
JNZ ENDOP ;TREAT AS SIMPLE OPERATOR IF NOT BDOS
|
|
; OTHERWISE, TREAT AS A RETURN INSTRUCTION
|
|
RETOP: CALL GETSP ;ADDRESS AT STACKTOP TO D,E
|
|
JMP ENDOP ;TREAT AS SIMPLE OPERATOR
|
|
;
|
|
CBDOS: ;COMPARE D,E WITH BDOS ADDRESS, RETURN ZERO FLAG IF EQUAL
|
|
LDA TRAPJMP+1
|
|
CMP E
|
|
RNZ
|
|
LDA TRAPJMP+2
|
|
CMP D
|
|
RET
|
|
;
|
|
GETOPA: ;GET OPERAND ADDRESS AND COMPARE WITH BDOS
|
|
POP B ;GET RETURN ADDRESS
|
|
POP H ;GET OPERAND ADDRESS
|
|
MOV E,M
|
|
INX H
|
|
MOV D,M
|
|
INX H
|
|
PUSH H ;UPDATED PC INTO STACK
|
|
PUSH B ;RETURN ADDRESS TO STACK
|
|
JMP CBDOS ;RETURN THROUGH CBDOS WITH ZERO FLAG SET
|
|
;
|
|
GETSP: ;GET RETURN ADDRESS FROM USER'S STACK TO D,E
|
|
LHLD SLOC
|
|
MOV E,M
|
|
INX H
|
|
MOV D,M
|
|
RET
|
|
;
|
|
CCOP: ;CALL CONDITIONAL OPERATOR
|
|
CALL GETOPA ;GET OPERAND ADDRESS TO D,E / COMPARE WITH BDOS
|
|
JZ CCOP1
|
|
; NOT THE BDOS, BREAK AT OPERAND ADDRESS AND NEXT ADDRESS
|
|
POP B ;NEXT ADDRESS TO B,C
|
|
PUSH B ;BACK TO STACK
|
|
MVI A,2 ;TWO BREAKPOINTS
|
|
JMP RETCAT ;RETURN FROM NBRK
|
|
;
|
|
CCOP1: ;BREAK ADDRESS AT NEXT LOCATION ONLY, WAIT FOR RETURN FROM BDOS
|
|
POP D
|
|
PUSH D ;BACK TO STACK
|
|
JMP ENDOP ;ONE BREAKPOINT ADDRESS
|
|
;
|
|
RSTOP: ;RESTART INSTRUCTION - CHECK FOR RST 7
|
|
MOV A,B
|
|
CPI RSTIN ;RESTART INSTRUCTION USED FOR SOFT INT
|
|
JNZ RST0
|
|
;
|
|
; SOFT RST, NO BREAK POINT SINCE IT WILL OCCUR IMMEDIATELY
|
|
XRA A
|
|
JMP RETCAT1 ;ZERO ACCUMULATOR
|
|
RST0: ANI 111000B ;GET RESTART NUMBER
|
|
MOV E,A
|
|
MVI D,0 ;DOUBLE PRECISION BREAKPOINT TO D,E
|
|
JMP ENDOP
|
|
;
|
|
PCOP: ;PCHL
|
|
LHLD HLOC
|
|
XCHG ;HL VALUE TO D,E FOR BREAKPOINT
|
|
CALL CBDOS ;BDOS VALUE?
|
|
JNZ ENDOP
|
|
; PCHL TO BDOS, USE RETURN ADDRESS
|
|
JMP RETOP
|
|
;
|
|
JMP ENDOP
|
|
;
|
|
SIMOP: ;SIMPLE OPERATOR, USE STACKED PC
|
|
POP D
|
|
PUSH D
|
|
JMP ENDOP
|
|
;
|
|
RCOND: ;RETURN CONDITIONAL
|
|
CALL GETSP ;GET RETURN ADDRESS FROM STACK
|
|
POP B ;B,C ALTERNATE LOCATION
|
|
PUSH B ;REPLACE IT
|
|
MVI A,2
|
|
JMP RETCAT ;TO SET FLAGS AND RETURN
|
|
;
|
|
DIMOP: ;DOUBLE PRECISION IMMEDIATE OPERATOR
|
|
POP D
|
|
INX D ;INCREMENTED ONCE, DROP THRU FOR ANOTHER
|
|
PUSH D ;COPY BACK
|
|
;
|
|
IMOP: ;SINGLE PRECISION IMMEDIATE
|
|
POP D
|
|
INX D
|
|
PUSH D
|
|
;
|
|
ENDOP: ;END OPERATOR SCAN
|
|
MVI A,1 ;SINGLE BREAKPOINT
|
|
RETCAT: ;RETURN FROM NBRK
|
|
INR A ;COUNT UP FOR G,...
|
|
STC
|
|
RETCAT1:
|
|
POP H ;RECALL NEXT ADDRESS
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
; OPCODE CATEGORY TABLES
|
|
OPLIST: DB 1111$1111B, 1100$0011B ;0 JMP
|
|
DB 1100$0111B, 1100$0010B ;1 JCOND
|
|
DB 1111$1111B, 1100$1101B ;2 CALL
|
|
DB 1100$0111B, 1100$0100B ;3 CCOND
|
|
DB 1111$1111B, 1100$1001B ;4 RET
|
|
DB 1100$0111B, 1100$0111B ;5 RST 0..7
|
|
DB 1111$1111B, 1110$1001B ;6 PCHL
|
|
DB 1100$0111B, 0000$0110B ;7 MVI
|
|
DB 1100$0111B, 1100$0110B ;8 ADI...CPI
|
|
DB 1100$1111B, 0000$0001B ;9 LXI
|
|
DB 1110$0111B, 0010$0010B ;10 LHLD SHLD LDA STA
|
|
DB 1100$0111B, 1100$0000B ;11 RCOND
|
|
DB 1111$0111B, 1101$0011B ;IN OUT
|
|
OPMAX EQU ($-OPLIST)/2
|
|
;
|
|
CATNO: DS 1 ;CATEGORY NUMBER SAVED IN NBRK
|
|
RETLOC: DS 2 ;RETURN ADDRESS TO USER FROM BDOS
|
|
TMODE: DS 1 ;TRACE MODE
|
|
TRACER: DS 2 ;TRACE COUNT
|
|
BREAKS: DS 7 ;#BREAKS/BKPT1/DAT1/BKPT2/DAT2
|
|
EXPLIST:DS 7 ;COUNT+(EXP1)(EXP2)(EXP3)
|
|
DISLOC: DS 2 ;DISPLAY LOCATION
|
|
DISMAX: DS 2 ;MAX VALUE FOR CURRENT DISPLAY
|
|
TDISP: DS 2 ;TEMP 16 BIT LOCATION
|
|
NEXTCOM:DS 2 ;NEXT LOCATION FROM COMMAND BUFFER
|
|
COMLEN: DB CSIZE ;MAX COMMAND LENGTH
|
|
CURLEN: DS 1 ;CURRENT COMMAND LENGTH
|
|
COMBUF: DS CSIZE ;COMMAND BUFFER
|
|
MLOAD: DS 2 ;MAX LOAD ADDRESS
|
|
DS SSIZE ;STACK AREA
|
|
STACK:
|
|
PLOC EQU STACK-2 ;PC IN TEMPLATE
|
|
HLOC EQU STACK-4 ;HL
|
|
SLOC EQU STACK-6 ;SP
|
|
ALOC EQU STACK-7 ;A
|
|
FLOC EQU STACK-8 ;FLAGS
|
|
BLOC EQU STACK-10 ;BC
|
|
DLOC EQU STACK-12;D,E
|
|
;
|
|
NOP ;FOR RELOCATION BOUNDARY
|
|
END
|