--- title: "2068 Disassembler and Monitor" id: 54569 type: "computer_media" slug: "disassembler-2" url: "http://localhost/computer_media/disassembler-2/" markdown_url: "http://localhost/computer_media/disassembler-2.md" published_at: "2024-06-02T17:41:02+00:00" modified_at: "2026-03-30T21:40:48+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/06/SCR-20240714-hksw.png" excerpt: "A full Z80 disassembler and machine code monitor that decodes every opcode prefix, supports symbol tables loaded from tape, and outputs to screen or printer." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" indiv: - name: "Bob Gilder" slug: "bob-gilder" taxonomy: "indiv" url: "http://localhost/indiv/bob-gilder/" genre: - name: "Programming" slug: "programming" taxonomy: "genre" url: "http://localhost/type/programming/" media_contents: - id: 51214 title: "CATS Library Tape 8" type: "computer_media" url: "http://localhost/computer_media/cats-library-tape-8/" - id: 55923 title: "Timex Sinclair Public Domain Library Tape 2003" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-2003/" media_type: "Program" programmers: - name: "Bob Gilder" slug: "bob-gilder" taxonomy: "indiv" url: "http://localhost/indiv/bob-gilder/" mediadate: "1984" images: - url: "http://localhost/wp-content/uploads/2024/06/SCR-20240714-hksw.png" media_type_tags: "Programming" --- # 2068 Disassembler and Monitor This program is a Z80 disassembler and machine code monitor for the Timex Sinclair 2068, written by Robert Gilder in 1984. It decodes all standard Z80 opcodes including the DD, FD, CB, and ED prefix groups, printing each instruction’s address, hex bytes, mnemonic, and operands to either the screen or a printer via the stream variable `hc`. The monitor section (lines 7500–7890) provides three utilities: a hex memory display, a hex machine code entry tool, and a byte-by-byte memory alteration tool. Symbols (user-defined labels with associated addresses) can be entered manually or loaded from tape, sorted via a bubble sort routine at line 8300, and substituted for raw addresses in the disassembly output. Relative branch offsets are displayed in signed decimal while absolute addresses are shown in four-digit hex, with optional symbol name substitution. *** ## Program Analysis ### Program Structure The program is organized into clearly delineated functional blocks, each beginning with a `REM` label. Execution starts at line 20 with a `GO TO 7500`, which launches the Monitor Menu. From there the user can invoke the disassembler (option 4), which is handled starting at line 100. The overall flow is: 1. Lines 0–30: Header, symbol array initialization, and `DEF FN s()` 2. Lines 100–910: Disassembler main loop and output formatting 3. Lines 1000–6320: Opcode decode routines, grouped by Z80 opcode group 4. Lines 7000–7295: Initialization, instructions display, symbol entry/sort/save 5. Lines 7500–7930: Machine Code Monitor (display, enter, alter memory) 6. Lines 8000–8730: Utility subroutines (defaults, opcode splitting, address resolution, hex formatting) 7. Lines 9000–9140: Input and hex conversion routines 8. Lines 9900–9980: `DATA` tables for mnemonics, condition codes, and ED-group block instructions ### Opcode Decoding Architecture The disassembler splits each opcode byte into three fields at line 8200 using integer arithmetic: `g = INT(c/64)` (bits 7–6), `t1 = INT(c/8) - g*8` (bits 5–3), and `t2 = c - t1*8 - g*64` (bits 2–0). The variable `rp = INT(t1/2)` extracts the register-pair index, and `t3 = (rp*2 <> t1)` is a parity flag used to distinguish e.g. INC from DEC. Dispatch to the four main opcode groups (00, 01, 10, 11) is done by `GO TO 1000+g*1000` at line 460, giving a clean computed jump. Within group 00 and group 11, a further computed `GO TO` using a packed string of line numbers dispatches to sub-handlers (lines 1010 and 4010). ### Prefix Handling DD and FD prefixes (IX and IY) are detected before the main dispatch at line 420. Subroutine 8100 sets `e$` to `"IX"` or `"IY"`, sets the displacement flag `e=1`, advances the opcode pointer, and increments the byte count `b`. Throughout the decoder, `e$` substitutes for `"HL"` in register names, and `e` offsets memory reads and byte counts to account for the displacement byte. The CB prefix (line 5000) and ED prefix (line 6000) each have their own subroutines, and the CB handler correctly handles the `DDCB`/`FDCB` two-prefix case by reading the opcode at `a+1+e*2`. ### Symbol Table Symbols are stored in the string array `s$()`, dimensioned with `ns+1` rows of 8 characters each. Each row uses columns 1–6 for the label name and columns 7–8 for the 16-bit address stored as two raw bytes (low byte first). The first row (`s$(1)`) stores the count of valid symbols in `CHR$ s`. The helper `DEF FN s(x)` at line 30 reconstructs a 16-bit integer from the two address bytes. At line 8300 a bubble sort orders symbols by address value, enabling the disassembly loop at line 340–415 to efficiently annotate label boundaries. Symbol lookup during address resolution occurs in subroutines 8400 and 8450. ### DATA Table Technique Mnemonic strings for the more regular opcode groups are stored in `DATA` statements at lines 9900–9980. The `RESTORE i: READ n` pattern at line 7310 positions the `DATA` pointer to a specific table, then iterates `t1+1` times to select the correct row. The format flag `n` (read first) is either 1 (mnemonic only) or 3 (mnemonic + two operand fields). Notably, some DATA values embed live BASIC expressions such as `FN b$(a+1)` and `"("+H$+")"` — these are read as string values and used verbatim or via `VAL$` at lines 1230–1240 to perform deferred evaluation, which is a sophisticated technique for embedding computed operands inside static data. ### Input and Address Parsing The general-purpose input routine at line 9000 uppercases all input by subtracting 32 from lowercase ASCII codes and sets the flag `end = NOT LEN a$` on empty (Enter-only) input, which propagates as a cancel/back signal throughout the program. Address parsing at line 8500 handles three formats: - Hexadecimal: trailing `H` triggers digit-by-digit conversion in a loop (line 8510) - Symbol name: matched against the symbol table (line 8520) - Decimal: validated character-by-character before using `VAL` (line 8540) Note a subtle bug at line 8530: if neither hex nor symbol matches, execution falls through to line 8540 for decimal conversion, but line 8530’s bare `RETURN` will be reached before line 8540 when the symbol loop exhausts without matching, causing `a` to remain unset (value -1 is never assigned in that path). Line 8540 appears to be unreachable after a failed symbol search. ### Hex Output Formatter Two hex formatting routines share a common core at line 9130. Line 9110 initializes `h$` to 4 spaces (for 16-bit output) and line 9120 initializes it to 2 spaces (for 8-bit output), then both fall through to the shared digit-extraction loop which fills `h$` right-to-left using `CHR$(x1 + CODE "0" + 7*(x1>9))` — the `+7` bridges the ASCII gap between `'9'` and `'A'`. ### Output Stream Selection The variable `hc` is set at line 200 to either 2 (screen) or 3 (printer), controlled by the Y/N prompt. All disassembly output uses `PRINT #hc;`, making the hard-copy option completely transparent to the formatting code. The monitor section always prints to the screen. ### Monitor Menu Dispatch At line 7570, the monitor dispatches to one of four routines using another packed-string computed `GO TO`: | Selection | Target | Function | | --- | --- | --- | | 1 | 7600 | Display memory in hex | | 2 | 7700 | Enter hex machine code | | 3 | 7800 | Alter memory byte-by-byte | | 4 | 0100 | Disassembler (only if present) | ### Disassembler Self-Detection Lines 7505–7507 implement a clever self-detection mechanism: the program runs `GO SUB 8000` and checks whether `e$` has been set. Line 8090 (`RETURN : REM no disassembler present`) would be the return point if the disassembler block were absent; since it is present, the full `8000` subroutine executes normally and sets `e$="HL"`, making `LEN e$ <> 0` true. The flag `d` is then used to conditionally show option 4 in the menu and to enable the disassembler dispatch. ### Notable Idioms - `VAL "number"` in `GO TO` and constant assignments (e.g., `LET DD=VAL "221"`) saves token storage compared to storing the integer literal directly. - `("STRING" AND condition)` is the standard Sinclair conditional string idiom, returning the string or `""` depending on the boolean value of the condition. - Bubble sort at lines 8320–8360 includes an early-exit flag `z` that triggers `RETURN` immediately when a pass completes with no swaps. - The `DEF FN r$(x)` at line 7005 is redefined in the initialization routine after the index register prefix is known, transparently substituting `e$` for `"HL"` when decoding `(HL)` references. ## 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 ```