A Z80 disassembler written entirely in BASIC. You give a start and end address, choose hexadecimal or decimal output and an offset, and the program lists the code one instruction a line: address, bytes in hex, then the mnemonic. The offset lets you disassemble code held at one address as if it ran at another. When the screen fills, it can copy the page to the printer (and feeds paper every third page) or ask whether to COPY it.
No author or date is given in the listing. It is saved as DISASSY.
Program Analysis
The program decodes each opcode into its octal fields (the top two bits, the middle three and the bottom three), then uses RESTORE 3000+100*CL+10*A(1)+A(2) to jump straight to the DATA line for that opcode group. CL is 1 after a CB prefix and 2 after ED, and IN records a DD or FD prefix. Each DATA pair is a three-character pattern (with - as a wildcard) and the mnemonic template.
The templates use punctuation as placeholders: &, ', !, ", #, $ and % are replaced from tables at lines 3333–3345 (register pairs, registers, conditions, ALU operations, bit numbers), found by RESTORE 3300+CODE of the placeholder character. * and - become (HL), (IX+d) or (IY+d) and HL, IX or IY. A . takes an immediate byte or a two-byte address, and / a displacement; JR and DJNZ targets are worked out and shown in brackets.
Notable Techniques
- Placeholder characters chosen so that
CODEof the character plus 3300 gives the line number of its substitution table. HALTis caught before the table search, since it sits whereLD (HL),(HL)would be.POKE 23658,8sets CAPS LOCK so the H/D and y/n answers come in as capitals.
Potential Issues
- The ALU table at line 3336 has
"SUB,", soSUBinstructions print asSUB,Band so on. - Opcodes with no entry (undocumented ones such as
SLL, or unusedEDcodes) make the search read past itsDATAand stop with an error. - Hex output is chosen only if the answer is exactly
H; any longer answer gives no address column. - The save line uses
LINE 1, which does not exist; the program starts at line 70 instead.
Source Code
70 POKE 23658,8
80 PAPER 0: INK 7: BORDER 0: CLS
100 LET O=0: LET X=O: LET T=O: DIM A$(3): DIM A(4): LET M=O: DIM X$(2): GO TO 420
120 REM CONVERSION
140 LET M=M+1
160 LET X=PEEK M
180 LET X$(1)=CHR$ ((48+INT (X/16) AND INT (X/16)<=9)+(55+INT (X/16) AND INT (X/16)>9)): LET X=X-INT (X/16)*16: LET X$(2)=CHR$ ((48+X AND X<=9)+(55+X AND X>9)): RETURN
200 LET N=M
220 LET X=INT (N/256): GO SUB 180: LET M$=X$: LET X=N-256*INT (N/256): GO SUB 180: LET M$=M$+X$: RETURN
240 REM DISPLACEMENT
250 IF IN<>0 AND CL=1 THEN LET M$=Z$: RETURN
260 GO SUB 120: PRINT ;X$;: LET X=PEEK M
270 LET X=(X AND X<128)+(X-256 AND X>127): LET M$=(X$ AND H$="H")+(STR$ X AND H$="D"): RETURN
280 GO SUB 260: LET N=M+1+X+MX
300 IF H$="D" THEN LET M$=STR$ X+" ("+STR$ N+")"
320 IF H$="H" THEN LET Z$=X$: GO SUB 220: LET M$=Z$+" ("+M$+")"
340 LET D$=D$+M$: PRINT TAB 15;D$: GO TO 440
360 REM V CHANGE
370 IF O+1>LEN D$ THEN GO TO 400
380 IF D$(O+1)="." THEN GO SUB 120: PRINT ;X$;: LET M$=X$: GO SUB 120: PRINT ;X$;: LET M$=(X$+M$ AND H$="H")+(STR$ (256*PEEK M+PEEK (M-1)) AND H$="D"): LET D$=D$( TO O-1)+D$(O+1 TO ): RETURN
400 GO SUB 120: PRINT ;X$;: LET M$=(X$ AND H$="H")+(STR$ PEEK M AND H$="D"): RETURN
420 FLASH 1: PRINT AT 8,8;"Z80 DISASSEMBLER": FLASH 0: INPUT " INPUT START ADDRESS#";M: LET M=M-1: INPUT " INPUT END ADDRESS#";MM: PRINT AT 20,9;"DO YOU WANT": INPUT "<H>EXADECIMAL OR <D>ECIMAL ADDRESS OUTPUT ";H$: INPUT "PRINTER OUTPUT (y/n) ";p$: CLS : INPUT AT 10,8;"OFFSET #";MX: LET PC=3
440 LET CL=0: LET IN=0: IF M+1>MM THEN GO SUB 820: GO TO 420
460 IF PEEK 23689=2 THEN GO SUB 820
480 LET M=M+1: LET N=M+MX: IF H$(1)="D" OR H$(1)="d" THEN LET M$=STR$ N: LET O=5-LEN M$: PRINT TAB O;M$;" ";
500 IF H$(1)="H" THEN GO SUB 220: PRINT M$;" ";
520 GO SUB 160
530 PRINT ;X$;
540 LET X=PEEK M: IF CL>0 THEN GO TO 580
550 IF X=203 OR X=237 THEN LET CL=(1 AND X=203)+(2 AND X=237): GO SUB 140: GO TO 530
560 IF X=221 OR X=253 THEN LET IN=(1 AND X=221)+(2 AND X=253): GO SUB 140: GO TO 530
570 IF X=118 THEN PRINT TAB 15;"HALT": GO TO 480
580 IF IN>0 AND CL>0 THEN GO SUB 270: LET Z$=M$: GO SUB 140: PRINT ;X$;: LET X=PEEK M
590 REM BINARY
600 LET D$="00000000": FOR O=1 TO 8: LET X=(X/2): LET D$(O)=STR$ (X+.5-INT X): NEXT O
620 LET A(1)=VAL D$(8)*2+VAL D$(7): LET A(2)=VAL D$(3)*4+VAL D$(2)*2+VAL D$(1): LET A(3)=VAL D$(6)*4+VAL D$(5)*2+VAL D$(4): LET A(4)=VAL D$(6)*2+VAL D$(5): LET A$(1)=STR$ A(3): LET A$(2)=D$(4): LET A$(3)=STR$ A(4)
640 REM SEARCH
660 RESTORE 3000+(100*CL+10*A(1)+A(2))
670 READ D$: FOR X=1 TO 3: IF D$(X)="-" THEN GO TO 700
680 IF A$(X)<>D$(X) THEN READ D$: GO TO 670
700 NEXT X: READ D$
720 REM VAR CHANGE
730 IF D$(1 TO 2)="JR" OR D$(1 TO 2)="DJ" THEN GO TO 280
740 FOR O=1 TO 14
750 IF O>LEN D$ THEN GO TO 810
760 LET B$=D$(O): IF B$>="!" AND B$<="'" THEN RESTORE 3300+CODE B$: LET T=(A(3) AND B$<"%")+(A(2) AND B$="%")+(A(4) AND B$>"%"): FOR N=0 TO T: READ M$: NEXT N: LET D$=D$( TO O-1)+M$+D$(O+1 TO ): LET B$=D$(O)
770 IF B$="*" OR B$="-" THEN RESTORE 3300+CODE B$: FOR N=0 TO IN: READ M$: NEXT N: LET D$=D$( TO O-1)+M$+D$(O+1 TO ): LET B$=D$(O)
780 IF B$="." OR B$="/" THEN GO SUB (360 AND B$=".")+(240 AND B$="/"): LET D$=D$( TO O-1)+M$+D$(O+1 TO )
800 NEXT O
810 PRINT TAB 15;D$: GO TO 440
820 REM OUTPUT
840 IF P$="N" OR P$="n" THEN BEEP .1,20: INPUT "COPY(y/n)?";M$: IF M$="N" OR M$="n" THEN CLS : RETURN
850 COPY : CLS
860 LET PC=PC-1: IF PC=0 THEN LET PC=3: FOR X=1 TO 8: LPRINT : NEXT X
880 RETURN
3000 DATA "0--","NOP","1--","EX AF,AF","2--","DJNZ ","3--","JR ","4--","JR NZ,","5--","JR Z,","6--","JR NC,","7--","JR C,"
3001 DATA "-0-","LD &,..","-1-","ADD -,&"
3002 DATA "0--","LD (BC),A","1--","LD A,(BC)","2--","LD (DE),A","3--","LD A,(DE)","4--","LD (..),-","5--","LD -,(..)","6--","LD (..),A","7--","LD A,(..)"
3003 DATA "-0-","INC &","-1-","DEC &"
3004 DATA "---","INC """
3005 DATA "---","DEC """
3006 DATA "---","LD "",."
3007 DATA "0--","RLCA","1--","RRCA","2--","RLA","3--","RRA","4--","DAA","5--","CPL","6--","SCF","7--","CCF"
3017 DATA "---","LD "",%"
3027 DATA "---","$%"
3030 DATA "---","RET #"
3031 DATA "-0-","POP '","-10","RET","-11","EXX","-12","JP (-)","-13","LD SP,-"
3032 DATA "---","JP #,.."
3033 DATA "0--","JP ..","2--","OUT (.),A","3--","IN A,(.)","4--","EX (SP),-","5--","EX DE,HL","6--","DI","7--","EI"
3034 DATA "---","CALL #,.."
3035 DATA "-0-","PUSH '","-1-","CALL .."
3036 DATA "---","$."
3037 DATA "0--","RST 00H (0)","1--","RST 08H (8)","2--","RST 10H (16)","3--","RST 18H (24)","4--","RST 20H (32)","5--","RST 28H (40)","6--","RST 30H (48)","7--","RST 38H (56)"
3107 DATA "0--","RLC %","1--","RRC %","2--","RL %","3--","RR %","4--","SLA %","5--","SRA %","7--","SRL %"
3117 DATA "---","BIT !,%"
3127 DATA "---","RES !,%"
3137 DATA "---","SET !,%"
3210 DATA "---","IN "",(C)"
3211 DATA "---","OUT (C),"""
3212 DATA "-0-","SBC HL,&","-1-","ADC HL,&"
3213 DATA "-0-","LD (..),&","-1-","LD &,(..)"
3214 DATA "---","NEG"
3215 DATA "-0-","RETN","-1-","RETI"
3216 DATA "0--","IM 0","2--","IM 1","3--","IM 2"
3217 DATA "0--","LD I,A","1--","LD R,A","2--","LD A,I","3--","LD A,R","4--","RRD","5--","RLD"
3220 DATA "4--","LDI","5--","LDD","6--","LDIR","7--","LDDR"
3221 DATA "4--","CPI","5--","CPD","6--","CPIR","7--","CPDR"
3222 DATA "4--","INI","5--","IND","6--","INIR","7--","INDR"
3223 DATA "4--","OUTI","5--","OUTD","6--","OTIR","7--","OTDR"
3333 DATA "0","1","2","3","4","5","6","7"
3334 DATA "B","C","D","E","H","L","*","A"
3335 DATA "NZ","Z","NC","C","PO","PE","P","M"
3336 DATA "ADD A,","ADC A,","SUB,","SBC A,","AND ","XOR ","OR ","CP "
3337 DATA "B","C","D","E","H","L","*","A"
3338 DATA "BC","DE","-","SP"
3339 DATA "BC","DE","-","AF"
3342 DATA "(HL)","(IX+/)","(IY+/)"
3345 DATA "HL","IX","IY"
4000 SAVE "DISASSY" LINE 1Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

