-
-
Save ruyrybeyro/e4af49aa29086b3a5b61a0d52c5d0d8f to your computer and use it in GitHub Desktop.
John Kerr's DIS-Z80 with Comments - adapted for the ZX Spectrum
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; Adapted for Z80 Spectrum syntax, assembled with pasmo | |
; Z80 disassembly routine in Z80 | |
ORG 50000 | |
LD A,2 ; upper screen | |
CALL 5633 ; open channel | |
LD DE,0 ; first address to disassembly | |
LD BC,30 ; number of lines | |
CALL _disz80 | |
; need to return to lower screen | |
LD A,1 ; lower screen | |
CALL 5633 ; open channel | |
CALL $15DE ; WAIT-KEY1 | |
RET | |
; This code is been found in a ZX Spectrum tool called UTILITY3 v1.3 | |
_disz80: | |
push ix | |
dizloop: | |
push bc | |
call DISASM | |
pop bc | |
ld a,13 | |
call CHROP | |
dec bc | |
ld a,b | |
or c | |
jr nz,dizloop | |
ld h,d | |
ld l,e | |
pop ix | |
ret | |
; ==================== | |
; DIS-Z80 was published in the SUBSET column of Personal Computer World 1987. | |
; The routine disassembles a single Z80 instruction at address DE. | |
; It is required to be followed by a routine called CHROP that outputs a | |
; single ASCII character. | |
; It was originally developed for CP/M on an Amstrad CPC128. | |
; The original ORG was $0100. I have added $5000 to all addresses. | |
; The stated aim was to write a Z80 disassembly routine in as short a space | |
; as possible and, at just over 1K (1090 bytes), it is a rather incredible | |
; program. | |
; The SUBSET editor David Barrow was able to trim only one byte from John | |
; Kerr's compact code. I've forgotten where so there's a challenge. | |
; ==================== | |
; STRUCTURAL CONCEPTS | |
; DATA | |
; | |
; Disassembled line: | |
; field 1: instruction 1st byte location (5 cols). | |
; field 2: instruction bytes (12 cols). | |
; field 3: mnemonic (5 cols). | |
; field 4: operand(s) (13 cols). | |
; | |
; Location address : ASCII hex (4 digits). | |
; Instruction bytes : ASCII hex (2 digits sequence). | |
; Operand data & : ASCII hex with appended "H" if >9, | |
; addresses : and preceeding "0" if 1st digit >9. | |
; Operand offsets : signed decimal, linked "+" or "-". | |
; PROGRAM DETAILS | |
; | |
; INPUT DE addresses 1st byte of instruction to disassemble. | |
; OUTPUT 35 character disassembled line to uotput device. | |
; STATE CHANGES DE updated to address 1st byte of next instruction. | |
; AF BC HL changed. | |
; I/O ERRORS None. | |
; OPTIMISATION Not given. | |
; INTERRUPT EFFECT May be interrupted and re-entered. | |
; LOCATION NEEDS Not specific. Not relocatable. PROMable. | |
; (Listing in this datasheet is assembled at 0100H) | |
; PROGRAM BYTES 695: code 206 + referenced tables:- | |
; GROUP2 (27), GROUP1 (168), GROUP3 (86), | |
; MONICS (208). | |
; STACK BYTES 46 maximum. | |
; CLOCK CYCLES Not given. | |
DISASM: CALL ADRSP ; Output the source pointer. | |
LD BC,$0900 ; Create an 18-byte output | |
LD HL,$2020 ; buffer in the stack area. | |
BUFFER: PUSH HL ; Buffer initially contains | |
DJNZ BUFFER ; 18 ASCII spaces (20H). | |
LD H,B ; Copy SP into HL, so the | |
LD L,C ; first byte of the output | |
ADD HL,SP ; buffer is addressed by HL. | |
PUSH BC ; Save original IX and | |
EX (SP),IX ; initialize to zero. | |
PUSH BC ; Initialize temp storage | |
PUSH BC ; (workspace) to all zeros. | |
ADD IX,SP ; Point IX to workspace. | |
PUSH HL ; Save buffer pointer; point | |
LD HL,GROUP3 ; to "ED" instruction group. | |
TRYNDX: CALL FETCH ; Fetch a byte of code. | |
LD B,C ; First check whether this | |
CP $ED ; is an "ED" instruction. | |
JR Z,CONFLG ; Yes; clear the index flag. | |
INC B ; Ready to set flag to "1" | |
CP $DD ; if the byte is 0DDH (an | |
JR Z,CONFLG ; instruction using IX). | |
INC B ; Ready to set flag to "2" | |
CP $FD ; if the byte is 0FDH (an | |
JR NZ,NOTNDX ; instruction using IY). | |
CONFLG: LD (IX+1),B ; Condition the index flag. | |
INC B ; Repeat index tests if the | |
DJNZ TRYNDX ; pre-byte was 0DDH or 0FDH. | |
JR NXBYTE ; Otherwise continue. | |
NOTNDX: LD C,A ; Save byte; check if index | |
LD A,(IX+1) ; flag was set (Allows any | |
OR A ; series of 0DDH and/or OFDH | |
JR Z,NODISP ; bytes, as per Zilog spec). | |
LD A,C ; If so, check for presence | |
CP $CB ; of any displacement. | |
JR Z,GETDIS ; 0CBH needs a displacement. | |
AND $44 ; A displacement is required | |
CP 4 ; if opcode has bit 2 set | |
JR Z,GETDIS ; and bit 6 reset. | |
LD A,C ; A displacemnet is required | |
AND $C0 ; if opcode has bit 6 set | |
CP $40 ; and bit 7 reset. | |
JR NZ,NODISP | |
GETDIS: CALL FETCH ; Get displacement if needed | |
LD (IX+2),A ; and save it in workspace. | |
NODISP: LD HL,GROUP1 ; "Main" instruction gorup. | |
LD A,C ; Recover opcode & check | |
CP $CB ; for OCBH ("bit" group). | |
JR NZ,NEWMSK ; No; start the search. | |
LD HL,GROUP2 ; Yes; point to "CB" group. | |
NXBYTE: CALL FETCH ; Fetch the last non-data | |
LD C,A ; byte and store it in C. | |
NEWMSK: LD A,(HL) ; Fetch a mask from table. | |
OR A ; Mask value of 0 indicates | |
JR Z,TABEND ; end of table; quit search. | |
AND C ; Otherwise mask the opcode | |
INC HL ; and address the mode byte. | |
NEWMOD: LD B,(HL) ; Fetch the mode byte in B. | |
INC HL ; Point to the match byte. | |
INC B ; Test if the mode is 0FFH | |
JR Z,NEWMSK ; and if so, get a new mak. | |
TRYMAT: CP (HL) ; Is the masked opcode | |
INC HL ; equal to the match byte? | |
JR Z,GETNDX ; Stop searching if it is. | |
BIT 7,(HL) ; index byte bit 7 is set if | |
INC HL ; address mode changes. | |
JR Z,TRYMAT ; No change; try next match. | |
JR NEWMOD ; Change; get a new mode. | |
GETNDX: LD A,(HL) ; Matched: fetch mnemonic | |
AND $7F ; index, mask bit 7, and | |
DEC B ; restore the mode byte. | |
TABEND: POP HL ; Save the source pointer | |
PUSH DE ; below the output buffer | |
PUSH HL ; pointer on stack. | |
EX DE,HL ; Point HL to start of the | |
LD HL,MONICS ; mnemonics table. | |
CALL XTRACT ; Copy mnemonic to buffer. | |
POP HL ; Restore output pointer | |
LD DE,5 ; and adjust to align | |
ADD HL,DE ; any operands present. | |
POP DE ; Restore source pointer. | |
LD A,B ; Test high-order B to see | |
AND $F0 ; if any "first" operand | |
JR Z,SECOND ; is present. | |
RRA ; Yes; move the operand | |
RRA ; index into the lower | |
RRA ; half of A. | |
RRA ; Then save | |
PUSH BC ; operand and opcode. | |
LD B,A ; Operand index in B. | |
LD A,C ; Restore opcode to A. | |
CALL OPRND1 ; Process the operand. | |
POP BC ; Restore the operand byte | |
LD A,B ; and opcode; test | |
AND $0F ; low-order B for any | |
JR Z,OPDONE ; "second" operand. | |
LD (HL),44 ; Opearnd index in B. | |
INC HL ; Restore opcode to A. | |
SECOND: LD A,B ; Check for the presence | |
AND $0F ; of a "second" operand. | |
LD B,A ; Operand index in B. | |
LD A,C ; Restore opcode to A. | |
CALL NZ,OPRND2 ; Process any operand. | |
OPDONE: LD A,3 ; Check how many bytes | |
SUB (IX+0) ; have been fetched. | |
POP HL ; Discard workspace. | |
POP HL | |
POP IX ; Restore index register. | |
JR C,OUTEXT ; 4 or more bytes fetched. | |
INC A ; Less than four bytes | |
LD B,A ; fetched; so output | |
ADD A,B ; enough spaces to | |
ADD A,B ; align the mnemonics. | |
LD B,A | |
SPACES: LD A,$20 ; Output spaces | |
CALL CHROP ; to start of | |
DJNZ SPACES ; mnemonic field. | |
OUTEXT: LD B,18 ; Set buffer byte count. | |
PUTOUT: DEC SP ; Copy stored text, byte | |
POP HL ; at a time, from output | |
LD A,H ; buffer on stack to | |
CALL CHROP ; the output channel. | |
DJNZ PUTOUT | |
RET ; Instruction disassembled. | |
;*********************** | |
GROUP2: defb $C0,$36,$40 | |
defb $04,$80,$2D,$C0,$BE | |
defb $FF,$F8,$06,$00,$33 | |
defb $08,$38,$10,$35,$18 | |
defb $3A,$20,$3F,$28,$40 | |
defb $30,$00,$38,$C1 | |
GROUP1: defb $FF,$00,$00 | |
defb $24,$07,$32,$0F,$37 | |
defb $17,$31,$1F,$36,$27 | |
defb $0D,$2F,$0B,$37,$3D | |
defb $3F,$06,$76,$14,$C9 | |
defb $30,$D9,$12,$F3,$0F | |
defb $FB,$91,$72,$C6,$02 | |
defb $CE,$01,$DE,$BC,$02 | |
defb $D6,$42,$E6,$03,$EE | |
defb $43,$F6,$25,$FE,$8C | |
defb $04,$08,$93,$01,$10 | |
defb $10,$18,$9D,$AF,$22 | |
defb $A2,$FA,$2A,$A2,$A7 | |
defb $32,$A2,$7A,$3A,$A2 | |
defb $03,$C3,$1C,$CD,$85 | |
defb $97,$D3,$AA,$79,$DB | |
defb $9B,$5F,$E3,$93,$0E | |
defb $E9,$9C,$05,$EB,$93 | |
defb $DF,$F9,$A2,$FF,$C0 | |
defb $B6,$40,$A2,$FF,$F8 | |
defb $76,$80,$02,$88,$01 | |
defb $98,$BC,$06,$90,$42 | |
defb $A0,$03,$A8,$43,$B0 | |
defb $25,$B8,$8C,$FF,$C7 | |
defb $0B,$04,$16,$05,$8E | |
defb $B2,$06,$A2,$20,$C0 | |
defb $B0,$23,$C2,$1C,$C4 | |
defb $85,$10,$C7,$BB,$FF | |
defb $CF,$D3,$01,$A2,$0D | |
defb $03,$16,$0B,$8E,$FD | |
defb $09,$82,$60,$C1,$2B | |
defb $C5,$AC,$FF,$E7,$21 | |
defb $20,$9D,$FF,$EF,$E7 | |
defb $02,$A2,$7E,$0A,$A2 | |
GROUP3: defb $FF,$00,$44 | |
defb $23,$45,$2F,$4D,$2E | |
defb $4E,$00,$67,$39,$6F | |
defb $34,$70,$00,$71,$00 | |
defb $A0,$21,$A1,$0A,$A2 | |
defb $1A,$A3,$29,$A8,$1F | |
defb $A9,$08,$AA,$18,$AB | |
defb $28,$B0,$20,$B1,$09 | |
defb $B2,$19,$B3,$27,$B8 | |
defb $1E,$B9,$07,$BA,$17 | |
defb $BB,$A6,$FF,$C7,$B8 | |
defb $40,$9B,$8B,$41,$AA | |
defb $FF,$CF,$FD,$42,$3C | |
defb $4A,$81,$AD,$43,$A2 | |
defb $DA,$4B,$A2,$FF,$E7 | |
defb $40,$46,$95,$FF,$F7 | |
defb $C7,$47,$A2,$7C,$57 | |
defb $A2,$FF,$00 | |
;_______________ | |
MONICS: defb $BF | |
defb 'A','D','C'+$80 ; ADC | |
defb 'A','D','D'+$80 ; ADD | |
defb 'A','N','D'+$80 ; AND | |
defb 'B','I','T'+$80 ; BIT | |
defb 'C','A','L','L'+$80 ; CALL | |
defb 'C','C','F'+$80 ; CCF | |
defb 'C','P','D','R'+$80 ; CPDR | |
defb 'C','P','D'+$80 ; CPD | |
defb 'C','P','I','R'+$80 ; CPIR | |
defb 'C','P','I'+$80 ; CPI | |
defb 'C','P','L'+$80 ; CPL | |
defb 'C','P'+$80 ; CP | |
defb 'D','A','A'+$80 ; DAA | |
defb 'D','E','C'+$80 ; DEC | |
defb 'D','I'+$80 ; DI | |
defb 'D','J','N','Z'+$80 ; DJNZ | |
defb 'E','I'+$80 ; EI | |
defb 'E','X','X'+$80 ; EXX | |
defb 'E','X'+$80 ; EX | |
defb 'H','A','L','T'+$80 ; HALT | |
defb 'I','M'+$80 ; IM | |
defb 'I','N','C'+$80 ; INC | |
defb 'I','N','D','R'+$80 ; INDR | |
defb 'I','N','D'+$80 ; IND | |
defb 'I','N','I','R'+$80 ; INIR | |
defb 'I','N','I'+$80 ; INI | |
defb 'I','N'+$80 ; IN | |
defb 'J','P'+$80 ; JP | |
defb 'J','R'+$80 ; JR | |
defb 'L','D','D','R'+$80 ; LDDR | |
defb 'L','D','D'+$80 ; LDD | |
defb 'L','D','I','R'+$80 ; LDIR | |
defb 'L','D','I'+$80 ; LDI | |
defb 'L','D'+$80 ; LD | |
defb 'N','E','G'+$80 ; NEG | |
defb 'N','O','P'+$80 ; NOP | |
defb 'O','R'+$80 ; OR | |
defb 'O','T','D','R'+$80 ; OTDR | |
defb 'O','T','I','R'+$80 ; OTIR | |
defb 'O','U','T','D'+$80 ; OUTD | |
defb 'O','U','T','I'+$80 ; OUTI | |
defb 'O','U','T'+$80 ; OUT | |
defb 'P','O','P'+$80 ; POP | |
defb 'P','U','S','H'+$80 ; PUSH | |
defb 'R','E','S'+$80 ; RES | |
defb 'R','E','T','I'+$80 ; RETI | |
defb 'R','E','T','N'+$80 ; RETN | |
defb 'R','E','T'+$80 ; RET | |
defb 'R','L','A'+$80 ; RLA | |
defb 'R','L','C','A'+$80 ; RLCA | |
defb 'R','L','C'+$80 ; RLC | |
defb 'R','L','D'+$80 ; RLD | |
defb 'R','L'+$80 ; RL | |
defb 'R','R','A'+$80 ; RRA | |
defb 'R','R','C','A'+$80 ; RA | |
defb 'R','R','C'+$80 ; RRC | |
defb 'R','R','D'+$80 ; RRD | |
defb 'R','R'+$80 ; RR | |
defb 'R','S','T'+$80 ; RST | |
defb 'S','B','C'+$80 ; SBC | |
defb 'S','C','F'+$80 ; SCF | |
defb 'S','E','T'+$80 ; SET | |
defb 'S','L','A'+$80 ; SLA | |
defb 'S','R','A'+$80 ; SRA | |
defb 'S','R','L'+$80 ; SRL | |
defb 'S','U','B'+$80 ; SUB | |
defb 'X','O','R'+$80 ; XOR | |
; OPRNDZ Operand Disassembler. To disassembler and output a valid | |
; Z80 machine code operand. | |
; OPRND1 Entry point for certain modes (see DATA) | |
; OPRND2 Entry point for certain modes (see DATA) | |
; STRUCTURAL CONCEPTS | |
; DATA | |
; | |
; Operand: Standard Z80 assembler format. | |
; The operand mode is determined by an input | |
; index (1 - 15) and by point of entry:- | |
; | |
; Index OPRND1 OPRND2 | |
; ------------------------------------------------------ | |
; 1 RST address Relative address | |
; 2 Condition Immediate byte | |
; 3 Bit number Immediate word | |
; 4 Interrupt mode AF,AF' | |
; 5 (SP) DE,HL | |
; 6 Register pair 8-bit source | |
; ------------------------------------------------------ | |
; 7 A | |
; 8 (C) | |
; 9 (port number) | |
; A (Absolute address) | |
; B 8-bit destination | |
; C I or R | |
; D 16-bit register | |
; E Address in 16-bit register | |
; F Index register | |
; | |
; PROGRAM DETAILS | |
; INPUT | |
; A = opcode. | |
; B = operand index. | |
; DE addresses next instruction byte. | |
; HL addresses next free byte in output buffer. | |
; (IX+0) = no. of instruction bytes fetched. | |
; (IX+1) = index register flag (1=IX, 2=IY, else 0). | |
; (IX+2) = displacement for any indexed instruction. | |
; | |
; OUTPUT Operand is in output buffer. | |
; DE and HL are updated. | |
; STATE CHANGES AF BC are changed. | |
; IX IY (IX+0,1,2) are unchanged. | |
;***************** | |
OPRND1: DJNZ CONDIT ; First entry point; is mode | |
RSTADR: AND $38 ; a restart address? If so, | |
JR DA ; isolate opcode bits 5-3. | |
OPRND2: DJNZ DAT8 ; 2nd entry point; is mode | |
RELADR: CALL FETCH ; PC relative? If so, fetch | |
LD C,A ; displacement & extend | |
RLA ; sign; put full 16-bit | |
SBC A,A ; signed displacemnet into | |
LD B,A ; BC. | |
EX DE,HL ; Move source pointer to HL, | |
PUSH HL ; save it on stack, compute | |
ADD HL,BC ; destination address & send | |
JR DHL ; to the output buffer. | |
CONDIT: RRA ; Opcode bits 2-0 are not | |
RRA ; needed for any of the | |
RRA ; following modes (OPRND1). | |
DJNZ BITNUM ; Is operand a condition? | |
BIT 4,A ; If so, check whether the | |
JR NZ,ABS ; address mode is relative | |
AND 3 ; or absolute. If relative, | |
ABS: AND 7 ; adjust condition index. | |
ADD A,$14 ; Index condition in table. | |
JR PS1 ; Copy it to the output buffer. | |
DAT8: DJNZ DAT16 ; Is operand immediate byte? | |
D8: CALL FETCH ; Fetch a byte. | |
JR DA ; Send to output buffer. | |
BITNUM: DJNZ INTMOD ; Is operand a bit number? | |
AND 7 ; Yes; isolate the index. | |
DA: LD C,A ; Move 8-bit data for output | |
SUB A ; from A into AC (so A=0) | |
JR DAC ; and send to output buffer. | |
DAT16: DJNZ EXAF ; Is operand an address? | |
D16: CALL FETCH ; Fetch low-order byte. | |
LD C,A ; Save it in C. | |
CALL FETCH ; Fetch high order byte. | |
DAC: EX DE,HL ; Exchange source & output | |
PUSH HL ; pointers. Save the source | |
LD H,A ; pointer & copy output data | |
LD L,C ; from AC into HL. | |
DHL: LD C,$F8 ; Specify hex conversion. | |
PUSH HL ; Save output for checking. | |
CALL CONVHL ; Perform ASCII conversion. | |
POP HL ; retrieve output value. | |
LD BC,$000A ; Check whether the value | |
OR A ; output was greater than 9. | |
SBC HL,BC ; Result of test in Cy. | |
POP HL ; Restore source & output | |
EX DE,HL ; pointers to their originall | |
RET C ; registers. Exit if output | |
LD (HL),'H' ; value was 9 or less; else | |
INC HL ; put "H" (denoting hex) | |
RET ; after the output & exit. | |
INTMOD: DJNZ STKTOP ; Is operand interrupt mode? | |
AND 3 ; Index the list of | |
ADD A,$1C ; interrupt modes (0,1,2) | |
PS1: JR PS3 ; Copy to output buffer. | |
STKTOP: LD C,$13 ; The constant operand (SP) | |
DEC B ; is entry number 19 in the | |
JR Z,PS2 ; RGSTRS table. | |
REG16P: DJNZ COMMON2 ; Is the operand register pair? | |
RRA ; Isolate the two bits of the | |
AND 3 ; opcode which determine the | |
CP 3 ; pair. Is it AF? | |
JR NZ,RX ; No; go to double register. | |
DEC A ; Yes, adjust pointer. | |
JR RNX ; Copy out register name. | |
EXAF: LD C,$0A ; The constant operand | |
DEC B ; AF,AF' is entry number 10 | |
JR Z,PS2 ; in the RGSTRS table. | |
EXDE: INC C ; The constant operand DE,HL | |
DEC B ; is entry number 11 in the | |
JR Z,PS2 ; RGSTRS table. | |
REG8S: DJNZ ACCUM ; Is operand 8-bit source? | |
R8: AND 7 ; Get register number. | |
CP 6 ; Is it a memory location? | |
JR NZ,PS3 ; No; so it's B/C/D/E/H/L/A. | |
LD (HL),'(' ; Yes; put the left parenthesis | |
INC HL ; into the output buffer. | |
CALL REGX ; Copy register HL/IX/IY. | |
LD A,(IX+2) ; Retrieve offset; check if | |
OR A ; it is zero. If so, don't | |
JR Z,RP ; bother to print it. | |
LD (HL),43 ; Otherwise, put a "+" sign | |
RLCA ; into the output buffer, but | |
RRCA ; now test the offset sign. | |
JR NC,POS ; If negative, change the | |
LD (HL),45 ; sign to "-" and negate | |
NEG ; the offset. | |
POS: INC HL ; Update the output pointer. | |
EX DE,HL ; Exchange pointers, saving | |
PUSH HL ; source pointer on stack. | |
LD H,B ; Put the absolute value | |
LD L,A ; of the offset into HL. | |
LD C,$FB ; Specify decimal and | |
CALL CONVHL ; perform ASCII convesion. | |
POP HL ; Restore pointers to their | |
EX DE,HL ; original registers. | |
JR RP ; Go put right parenthesis. | |
ACCUM: RRA ; Opcode bits 2-0 can now | |
RRA ; be discarded by OPRND2. | |
RRA | |
COMMON2: | |
LD C,7 ; OPRND1 and OPRND2 merge. | |
DEC B ; Accumulator addressing; | |
JR Z,PS2 ; put "A" to output buffer. | |
PORTC: DEC C ; Constant operand "(C)" is | |
DJNZ IDAT8 ; entry number 6 in RGSTRS. | |
PS2: LD A,C ; Copy string number into A. | |
PS3: JR PS4 ; Go copy out the string. | |
IDAT8: DJNZ IDAT16 ; Is operand a constant port | |
LD (HL),'(' ; number? If so, that's just | |
INC HL ; like an immediate byte but | |
CALL D8 ; inside brackets. | |
JR RP ; Close the brackets. | |
IDAT16: DJNZ REG8 ; Is operand an address for | |
LD (HL),'(' ; data? That's just like a | |
INC HL ; CALL or JP address but | |
CALL D16 ; inside brackets. | |
JR RP ; Close the brackets. | |
REG8: DEC B ; Use 8-bit source routine | |
JR Z,R8 ; for an 8-bit destination. | |
IPAREF: DJNZ REG16 ; Is operand I or R? | |
AND 9 ; Yes, then copy the correct | |
JR PS4 ; string from RGSTRS. | |
REG16: RRA ; Is operand a | |
DJNZ IREG16 ; 16-bit register? | |
R16: AND 3 ; Check for index register. | |
RX: CP 2 ; If it's an index register, | |
JR Z,REGX ; go use separate routine. | |
RNX: ADD A,$0C ; Not an index register; | |
JR PS4 ; point ot BC/DE/AF/SP. | |
IREG16: DJNZ REGX ; Is the operand an address | |
LD (HL),'(' ; contained in a register? | |
INC HL ; Then just put brackets | |
CALL R16 ; round the result from R16. | |
RP: LD (HL),')' ; Put right parenthesis in | |
INC HL ; output buffer, update | |
RET ; pointer, then exit. | |
REGX: LD A,(IX+1) ; Use the index flag to | |
ADD A,$10 ; select an index register. | |
PS4: EX DE,HL ; Copy a string from RGSTRS. | |
PUSH HL ; Exchange pointers; save | |
LD HL,RGSTRS ; source pointer; point HL | |
CALL XTRACT ; to start of table and | |
POP HL ; copy out the string. Then | |
EX DE,HL ; restore pointers to their | |
RET ; original registers, exit. | |
;************* | |
RGSTRS: defb 'B' +$80 | |
defb 'C' +$80 | |
defb 'D' +$80 | |
defb 'E' +$80 | |
defb 'H' +$80 | |
defb 'L' +$80 | |
defb '(','C',')' +$80 | |
defb 'A' +$80 | |
defb 'I' +$80 | |
defb 'R' +$80 | |
defb 'A','F',',','A','F','\' +$80 | |
defb 'D','E',',','H','L' +$80 | |
defb 'B','C' +$80 | |
defb 'D','E' +$80 | |
defb 'A','F' +$80 | |
defb 'S','P' +$80 | |
defb 'H','L' +$80 | |
defb 'I','X' +$80 | |
defb 'I','Y' +$80 | |
defb '(','S','P',')' +$80 | |
defb 'N','Z' +$80 | |
defb 'Z' +$80 | |
defb 'N','C' +$80 | |
defb 'C' +$80 | |
defb 'P','O' +$80 | |
defb 'P','E' +$80 | |
defb 'P' +$80 | |
defb 'M' +$80 | |
defb '0' +$80 | |
defb '?' +$80 | |
defb '1' +$80 | |
defb '2' +$80 | |
;******************** | |
CONVHL: SUB A | |
CVHL1: PUSH AF | |
SUB A | |
LD B,16 | |
CVHL2: ADD A,C | |
JR C,CVHL3 | |
SUB C | |
CVHL3: ADC HL,HL | |
RLA | |
DJNZ CVHL2 | |
JR NZ,CVHL1 | |
CP 10 | |
INC B | |
JR NC,CVHL1 | |
CVHL4: CP 10 | |
SBC A,$69 | |
DAA | |
LD (DE),A | |
INC DE | |
POP AF | |
JR NZ,CVHL4 | |
RET | |
;**************** | |
XTRACT: OR A | |
JR Z,COPY | |
SKIP: BIT 7,(HL) | |
INC HL | |
JR Z,SKIP | |
DEC A | |
JR NZ,SKIP | |
COPY: LD A,(HL) | |
RLCA | |
SRL A | |
LD (DE),A | |
INC DE | |
INC HL | |
JR NC,COPY | |
RET | |
;******************* | |
FETCH: LD A,(DE) | |
INC DE | |
INC (IX+0) | |
PUSH AF | |
CALL BYTSP | |
POP AF | |
RET | |
ADRSP: LD A,D | |
CALL BYTOP | |
LD A,E | |
BYTSP: CALL BYTOP | |
LD A,$20 | |
JR CHROP | |
BYTOP: PUSH AF | |
RRA | |
RRA | |
RRA | |
RRA | |
CALL HEXOP | |
POP AF | |
HEXOP: AND $0F | |
CP 10 | |
SBC A,$69 | |
DAA | |
; ----------------------------------- | |
; | |
; End of John Kerr's DIS-Z80 routine. | |
; | |
; The next routine outputs a character. | |
; | |
; ------------------------------------- | |
CHROP: PUSH HL | |
PUSH DE | |
PUSH BC | |
push AF ; parameter passing | |
RST 16 | |
pop AF | |
POP BC | |
POP DE | |
POP HL | |
RET |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment