Machine language disassembler in BASIC.
Content
Source Code
0 REM RESET ROBERT GILDER 1984
5 REM 2068 DISASSEMBLER & MONITOR
10 LET ns=0: DIM s$(ns+1,8): LET s$(1)=CHR$ 0
20 GO TO 7500
30 DEF FN s(x)=CODE s$(x,7)+256*CODE s$(x,8)
100 GO SUB 7000
110 LET a$="ENTER to continue": GO SUB 9000
120 IF CODE s$(1) THEN GO TO 200
130 LET a$="Enter symbols?(Y/N)": GO SUB 9000: IF FN y() THEN GO SUB 7200: GO SUB 8300
200 LET a$="Hard copy (Y/N)?": GO SUB 9000: LET hc=2+FN y()
210 CLS
300 IF LEN INKEY$ THEN GO TO 300
305 LET a$="Enter start address:": GO SUB 9000: IF end THEN GO TO 20
310 GO SUB 8500: IF a<0 THEN GO TO 305
320 IF LEN INKEY$ THEN GO TO 320
330 PRINT #hc;"Addr Hex OP Operand/Notes"''
340 FOR x=2 TO CODE s$(1)+1: LET xa=FN s(x): IF x>xa THEN NEXT x: LET xa=1e31
350 LET xs=x
400 REM Main loop
405 GO SUB 8000
410 IF LEN INKEY$ THEN GO TO 300
415 IF a>=xa THEN PRINT #hc;TAB 13;s$(xs TO 6);":": LET xs=xs+1: LET xa=1e31: IF xs<=CODE s$(1)+1 THEN LET xa=FN s(xs): GO TO 415
420 LET c=PEEK a: IF c=DD OR c=FD THEN GO SUB 8100
425 LET p$="BCDE"+e$+"AF": LET q$="BCDE"+e$+"SP": LET r$="BCDEHLMA"
430 IF c=CB THEN GO SUB 5000: GO TO 500
440 IF c=ED THEN GO SUB 6000: GO TO 500
450 GO SUB 8200
460 GO SUB 1000+g*1000
500 REM Print
510 LET h=a: GO SUB 9100: PRINT #hc;h$;" ";
520 FOR n=1 TO b: LET h=PEEK (a+n-1): GO SUB 9120: PRINT #hc;h$;: NEXT n
530 PRINT #hc;TAB 14;j$;TAB 19;k$;"," AND L$<>"";L$;" ";">" AND n$<>"";n$
900 LET a=a+b
910 GO TO 400
1000 REM Group 00
1010 GO TO VAL "10201100120013001400140016001700"(t2*4+1 TO t2*4+4)
1020 LET i=9900: GO SUB 7300: IF t1<2 THEN RETURN
1050 LET b=b+1: LET h=a+2+FN p(a+1): GO SUB 9100: GO SUB 8450: LET n$=h$
1060 RETURN
1100 IF t3 THEN LET j$="ADD": LET k$=e$: LET L$=FN p$(q$): RETURN
1120 LET j$="LD": LET k$=FN p$(q$): LET h=a+1+e: GO SUB 8400: LET L$=h$: RETURN
1200 LET i=9905: GO SUB 7300: IF t1<4 THEN RETURN
1220 LET h=a+1+e: GO SUB 8400
1230 IF t3 THEN LET L$=VAL$ L$: RETURN
1240 LET k$=VAL$ k$
1250 RETURN
1300 LET j$=("DEC" AND t3)+("INC" AND (NOT t3)): LET k$=FN p$(q$): RETURN
1400 LET j$=("DEC" AND t2=5)+("INC" AND t2=4)
1420 LET k$=FN r$(t1): LET b=b+e
1430 RETURN
1600 LET j$="LD": LET k$=FN r$(t1): LET h=a+1+e*2: GO SUB 8600: LET b=b+e: LET L$=h$: RETURN
1700 LET i=9910: GO SUB 7300
1710 RETURN
2000 REM Group 01
2010 IF t1=6 AND t2=6 THEN LET j$="HALT": RETURN
2020 LET j$="LD"
2030 LET k$=FN r$(t1): LET L$=FN r$(t2)
2040 LET b=b+e
2050 RETURN
3000 REM Group 10
3010 LET k$=FN r$(t2): LET b=b+e
3100 LET i=9915: GO SUB 7300
3105 IF t1<4 AND t1<>2 THEN LET L$=k$: LET k$="A"
3110 RETURN
4000 REM Group 11
4010 GO TO 4100+t2*100
4020 LET j$="??": RETURN
4100 LET j$="RET": GO SUB 7400: RETURN
4200 IF t3 THEN LET i=9920: GO SUB 7300: RETURN
4210 LET j$="POP": LET k$=FN p$(p$): RETURN
4300 LET j$="JP": GO SUB 7400: LET h=a+1: GO SUB 8400: LET L$=h$: RETURN
4400 IF NOT t1 THEN LET h=a+1: GO SUB 8400
4410 IF t1=2 OR t1=3 THEN LET h=PEEK (a+1): GO SUB 9120: LET b=b+1
4420 LET i=9925: GO SUB 7300: RETURN
4500 LET j$="CALL": GO SUB 7400: LET h=a+1: GO SUB 8400: LET L$=h$: RETURN
4600 IF NOT t3 THEN LET j$="PUSH": LET k$=FN p$(p$): RETURN
4610 IF t1<>1 THEN GO TO 4020
4620 LET j$="CALL": LET h=a+1: GO SUB 8400: LET k$=h$: RETURN
4700 LET h=PEEK (a+1): GO SUB 9120: LET k$=h$: LET b=b+1: GO TO 3100
4800 LET j$="RST": LET h=t1*8: GO SUB 9120: LET k$=h$
4810 RETURN
5000 REM CB Group
5010 LET b=b+1+e: LET c=PEEK (a+1+e*2): GO SUB 8200
5100 IF NOT g THEN LET i=9930: GO SUB 7300: LET k$=FN r$(t2): RETURN
5110 LET j$="BITRESSET"((g-1)*3+1 TO (g-1)*3+3)
5120 LET k$=CHR$ (t1+CODE "0")
5130 LET L$=FN r$(t2)
5140 RETURN
6000 REM ED group
6010 LET b=b+1: LET c=PEEK (a+1): GO SUB 8200
6020 IF g=2 THEN GO TO 6300
6030 IF g<>1 THEN LET j$="??": RETURN
6040 GO TO VAL "60506060607061006200621062206230"(t2*4+1 TO t2*4+4)
6050 LET j$="IN": LET L$="(C)": LET k$=FN r$(t1): RETURN
6060 LET j$="OUT": LET k$="(C)": LET L$=FN r$(t1): RETURN
6070 LET j$=("ADC" AND t3)+("SBC" AND (NOT t3)): LET k$=e$: LET L$=FN p$(q$): RETURN
6100 LET j$="LD": LET h=a+2: GO SUB 8400: LET h$="("+h$+")"
6120 LET k$=FN p$(q$): LET L$=h$
6130 IF NOT t3 THEN LET L$=k$: LET k$=h$
6140 RETURN
6200 LET j$="NEG": RETURN
6210 LET j$=("RETI" AND t1)+("RETN" AND (NOT t1)): RETURN
6220 LET j$="IM": LET k$=CHR$ (t1+CODE "0"): RETURN
6230 LET i=9935: GO SUB 7300
6240 RETURN
6300 RESTORE 9940+t2*10
6310 FOR x=1 TO t1-3: READ j$: NEXT x
6320 RETURN
7000 REM Initialize
7005 DEF FN r$(x)=(r$(x+1) AND r$(x+1)<>"M")+(FN i$(a+1+e) AND r$(x+1)="M")
7010 DEF FN p(x)=PEEK x-(256*(PEEK x>127))
7015 DEF FN b$(x)=("+" AND FN p(x)>=0)+STR$ FN p(x)
7020 DEF FN i$(x)="("+e$+(FN b$(x) AND e)+")"
7025 DEF FN p$(x$)=x$(rp*2+1 TO rp*2+2)
7030 DEF FN y()=CHR$ CODE a$="Y"
7035 DEF FN n(x$)=(x$>="0" AND x$<="9")
7040 LET p$="BCDEHLAF": LET q$="BCDEHLSP": LET r$="BCDEHLMA"
7045 LET DD=VAL "221": LET FD=VAL "253"
7050 LET ED=VAL "237": LET CB=VAL "203"
7070 LET ramtop=1+PEEK 23730+256*PEEK 23731
7100 REM Instructions
7110 CLS : PRINT " *** 2068 DISASSEMBLER ***"
7130 PRINT '"All the values are shown in hex with the exception of relative offset value, which are shown indecimal(e.g. JR +19 or LD (IY-8),FF)."
7140 PRINT '"Addresses may be entered in hex (e.g. 43a2h) or decimal, or evencertain System Variable names, like RAMTOP."
7190 RETURN
7200 REM Enter symbol name
7210 LET a$="Load symbols from tape?": GO SUB 9000: IF FN y() THEN INPUT "Name:"; LINE a$: LOAD a$ DATA s$(): RETURN
7220 FOR s=2 TO ns+1
7230 LET a$="Enter symbol name:": GO SUB 9000: IF end THEN LET s=s-2: GO TO 7280
7240 LET s$(s, TO 6)=a$
7250 LET a$="Enter address:": GO SUB 9000: IF end THEN GO TO 7250
7255 GO SUB 8500: IF a<0 THEN GO TO 7250
7260 LET s$(s,7 TO )=CHR$ (a-INT (a/256)*256)+CHR$ (INT (a/256))
7270 PRINT s$(s, TO 6),a
7275 NEXT s: LET s=ns
7280 LET s$(1)=CHR$ s
7290 LET a$="Save symbols on tape?": GO SUB 9000: IF FN y() THEN INPUT "Name:"; LINE a$: SAVE a$ DATA s$()
7295 RETURN
7300 REM Create operand
7310 RESTORE i: READ n
7320 FOR x=1 TO t1+1
7330 READ j$: IF n=3 THEN READ k$,L$
7340 NEXT x
7390 RETURN
7400 REM Condition codes
7410 RESTORE 9980: FOR x=1 TO t1+1: READ k$: NEXT x
7420 RETURN
7500 REM Machine Code Monitor-ZXMCOM
7501 REM ROBERT GILDER 1984
7505 LET e$="": GO SUB 8000: LET d=(LEN e$<>0): REM DISASM check
7510 LET ramtop=PEEK 23730+256*PEEK 23731+1: IF NOT d THEN LET s$=CHR$ 0: REM set ramtopvalue
7520 CLS : PRINT TAB 10;"MONITOR MENU"''" (1) Display memory in hex"'" (2) Enter hex machine code"'" (3) Alter memory"
7530 IF d THEN PRINT " (4) Disassemble memory"
7540 PRINT ''"Null Finish Program"
7550 LET a$="Enter your selection:": GO SUB 9000: IF end THEN STOP : GO TO 7520
7560 IF VAL a$<1 OR VAL a$>3+d THEN GO TO 7550
7570 CLS : GO TO VAL "7600770078000100"((VAL a$-1)*4+1 TO (VAL a$-1)*4+4)
7600 REM display memory
7610 IF LEN INKEY$ THEN GO TO 7610
7620 GO SUB 8700: IF end THEN GO TO 7500
7630 FOR a=a TO a+65535 STEP 8: LET h=a: GO SUB 9100: PRINT h$;" ";
7640 FOR b=a TO a+7: LET h=PEEK b: GO SUB 9120: PRINT h$;" ";: NEXT b
7650 PRINT : IF LEN INKEY$ THEN GO TO 7600
7660 NEXT a: GO TO 7500
7700 REM Enter machine code
7705 IF LEN INKEY$ THEN GO TO 7705
7710 GO SUB 8700: IF end THEN GO TO 7500
7715 PRINT AT 10,0;"Current address: ";a;"(";: LET h=a: GO SUB 9100: PRINT h$;")"
7720 LET a$="Enter hex: ": GO SUB 9000: IF end THEN GO TO 7500
7725 PRINT AT 21,0,,
7730 IF LEN a$<>INT (LEN a$/2)*2 THEN PRINT AT 21,0; FLASH 1;"LENGTH ERROR"; FLASH 0;" - re-enter": GO TO 7720
7735 FOR X=1 TO LEN a$-1 STEP 2: GO SUB 7900
7740 IF x1*16+x2>255 THEN PRINT AT 21,0; FLASH 1;"RANGE ERROR"; FLASH 0;" - re-enter remainder": GO TO 7715
7745 POKE a,x1*16+x2
7750 LET a=a+1
7755 NEXT x
7760 GO TO 7715
7800 REM Alter memory
7810 IF LEN INKEY$ THEN GO TO 7810
7820 GO SUB 8700: IF end THEN GO TO 7500
7830 LET h=a: GO SUB 9100: LET x$=h$: LET h=PEEK a: GO SUB 9120
7840 LET a$=x$+" "+h$+"-": GO SUB 9000: IF end THEN GO TO 7880
7850 IF a$="." THEN GO TO 7500
7860 IF LEN a$>2 THEN LET a$=a$( TO 2)
7870 LET x=1: GO SUB 7900: POKE a,x1*16+x2
7880 PRINT x$;" ";h$;"-";a$
7890 LET a=a+1: GO TO 7830
7900 REM convert a$(x) to binary
7910 LET x1=CODE a$(x)-CODE "0"-7*(a$(x)>"9")
7920 LET x2=CODE a$(x+1)-CODE "0"-7*(a$(x+1)>"9")
7930 RETURN
8000 REM Reset defaults
8010 LET e$="HL"
8020 LET e=0: LET b=1
8030 LET j$="": LET k$="": LET L$="": LET h$="": LET n$=""
8040 RETURN
8090 RETURN : REM no disassembler present
8100 REM DD/FD opcode
8110 LET e$=("IX" AND c=DD)+("IY" AND c=FD)
8120 LET e=1: LET b=b+1
8130 LET c=PEEK (a+1)
8140 RETURN
8200 REM Split opcode
8210 LET g=INT (c/64): LET t1=INT (c/8)-g*8: LET t2=c-t1*8-g*64
8220 LET rp=INT (t1/2): LET t3=(rp*2<>t1)
8230 RETURN
8300 REM Sort symbols
8310 PRINT AT 21,0;"Sorting...."
8320 FOR x=2 TO CODE s$(1)+1: LET z=1: FOR y=2 TO CODE s$(1)-x+2
8330 IF FN s(y)>FN s(y+1) THEN LET x$=s$(y): LET s$(y)=s$(y+1): LET s$(y+1)=x$: LET z=0
8340 NEXT y: IF z THEN RETURN
8350 NEXT x
8360 RETURN
8400 REM Get address in h$
8410 LET h=PEEK h+256*PEEK (h+1): GO SUB 9100
8420 LET b=b+2
8450 IF NOT CODE s$(1) THEN RETURN
8460 FOR x=2 TO CODE s$(1)+1
8470 IF h>FN s(x) THEN NEXT x: RETURN
8480 IF h=FN s(x) THEN LET h$=s$(x, TO 6)
8490 RETURN
8500 REM Create true address
8510 IF a$(LEN a$)="H" THEN LET a=0: FOR x=1 TO LEN a$-1: LET a=a*16+CODE a$(x)-CODE "0"-7*(a$(x)>"9"): NEXT x: RETURN
8520 FOR x=2 TO CODE s$(1)+1: IF a$=s$(x, TO LEN a$*(LEN a$<7)) THEN LET a=CODE s$(x,7)+256*CODE s$(x,8): RETURN
8530 RETURN
8540 LET a=-1: FOR x=1 TO LEN a$: IF a$(x)>="0" AND a$(x)<="9" THEN NEXT x: LET a=VAL a$
8550 RETURN
8600 REM Byte value
8610 LET h=PEEK h: GO SUB 9120: LET b=b+1
8620 RETURN
8700 REM Start address
8710 LET a$="Enter start address:": GO SUB 9000: IF end THEN RETURN
8720 GO SUB 8500: IF a<0 THEN GO TO 8710
8730 RETURN
9000 REM Line input
9010 INPUT (a$+" "); LINE a$: LET end=NOT LEN a$
9020 FOR x=1 TO LEN a$: LET a$(x)=CHR$ (CODE a$(x)-32*(a$(x)>="a")): NEXT x
9030 RETURN
9100 REM h$=hex$(h)
9110 LET h$=" ": GO TO 9130
9120 LET h$=" "
9130 LET h1=h: FOR x=LEN h$ TO 1 STEP -1: LET x1=h1-INT (h1/16)*16: LET h$(x)=CHR$ (x1+CODE "0"+7*(x1>9)): LET h1=INT (h1/16): NEXT x
9140 RETURN
9900 DATA 3,"NOP","","","EX","AF","AF","DJNZ",FN b$(a+1),"","JR",FN B$(a+1),"","JR","NZ",FN B$(a+1),"JR","Z",FN B$(a+1),"JR","NC",FN B$(a+1),"JR","C",FN B$(a+1)
9905 DATA 3,"LD","(BC)","A","LD","A","(BC)","LD","(DE)","A","LD","A","(DE)","LD","""(""+H$+"")""","HL","LD","HL","""(""+H$+"")""","LD","""(""+h$+"")""","A","LD","A","""(""+h$+"")"""
9910 DATA 1,"RLCA","RRCA","RLA","RRA","DAA","CPL","SCF","CCF"
9915 DATA 1,"ADD","ADC","SUB","SBC","AND","XOR","OR","CP"
9920 DATA 3,"??","","","RET","","","??","","","EXX","","","??","","","JP","("+E$+")","","??","","","LD","SP",E$
9925 DATA 3,"JP",H$,"","??","","","OUT","("+H$+")","A","IN","A","("+H$+")","EX",E$,"(SP)","EX","DE",E$,"DI","","","EI","",""
9930 DATA 1,"RLC","RRC","RL","RR","SLA","SRA","??","SRL"
9935 DATA 3,"LD","I","A","LD","R","A","LD","A","I","LD","A","R","RRD","","","RLD","",""
9940 DATA "LDI","LDD","LDIR","LDDR"
9950 DATA "CPI","CPD","CPIR","CPDR"
9960 DATA "INI","IND","INIR","INDR"
9970 DATA "OUTI","OUTD","OTIR","OTDR"
9980 DATA "NZ","Z","NC","C","PO","PE","P","M"
9999 STOP