--- title: "ZX Spectrum Editor/Assembler" id: 53833 type: "computer_media" slug: "dev-assem" url: "http://localhost/computer_media/dev-assem/" markdown_url: "http://localhost/computer_media/dev-assem.md" published_at: "2024-05-13T19:02:00+00:00" modified_at: "2026-03-30T21:46:30+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "A two-pass Z80 assembler with a built-in line editor, label resolution, and a DATA-driven instruction encoder — all in pure BASIC with a machine-code insert helper." 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/" genre: - name: "Machine Language" slug: "machine-language" taxonomy: "genre" url: "http://localhost/type/machine-language/" - name: "Programming" slug: "programming" taxonomy: "genre" url: "http://localhost/type/programming/" media_contents: - id: 55361 title: "SINCUS Exchange Tape 102 – Utilities & Business" type: "computer_media" url: "http://localhost/computer_media/sincus-exchange-tape-102-utilities-business/" media_type: "Program" mediadate: "1983" images: - url: "http://localhost/wp-content/uploads/2024/05/zx-spectrum-editor-assembler.png" media_type_tags: "Machine Language, Programming" --- This program is a full Z80 assembler and source-code editor. The editor stores assembly source in a string array `q$` using a compact internal record format (label number, opcode, operand lengths, and machine-code bytes packed together), and a two-pass assembler resolves forward label references stored in a 99-element numeric array `l()`. Instruction encoding is driven entirely by DATA statements beginning at line 812, using a hash-based RESTORE lookup (line 110) that computes an index from character codes of the mnemonic to jump directly to the relevant DATA block. A short 19-byte machine-code routine (POKEd in at line 2004 using the data at line 2006) implements a fast block-insert operation used when inserting new source lines into the middle of the buffer. *** ## Program Analysis ### Program Structure The program is organized into several functional regions. Initialization runs from lines 800–806, the editor loop from lines 20–52, display/listing at lines 30–34, the two-pass assembler at lines 200–270, the instruction-decoding library at lines 300–530, machine-code byte-builders at lines 600–616, the mnemonic-input and opcode-lookup routine at lines 100–130, and the DATA tables for all Z80 mnemonics from lines 812 to 1379. A 19-byte machine-code helper is installed at startup (lines 2000–2006). ### Source Buffer Format All assembly source is packed into a single string `q$`. Each record is 8 bytes of header followed by variable-length fields: - Byte 0: label number (0 = no label) - Bytes 1–4: 4-character mnemonic (e.g. `"LD "`) - Byte 5: length of operand text - Byte 6: length of machine-code bytes - Byte 7: reserved / instruction-type flag - Following bytes: operand text, then machine-code bytes The variable `last` tracks the next free position; `lns` counts lines; `mc` tracks total machine-code byte count. Navigation through the buffer is done by advancing `ptr` using `FN c(5)` and `FN c(6)` to read field lengths. ### Defined Functions | Function | Purpose | | --- | --- | | `FN r(x,y,z$)` | Tests whether `z$` falls in the character range [x,y] — used for digit/letter detection | | `FN a(x)` | Reads a little-endian 16-bit word from memory address `x` | | `FN q$(x,y)` | Returns a substring of `q$` relative to current `ptr` | | `FN c(x)` | Returns the numeric CODE of one byte from `q$` at `ptr+x` | ### Mnemonic Hash Lookup When an opcode is entered, line 110 computes a hash into the DATA tables: `LET a=2*CODE e$+5*CODE e$(2)+6*CODE e$(3)+4*CODE e$(4)` This hash is used directly as a `RESTORE a` target, jumping to the DATA line for that mnemonic. Because DATA line numbers are chosen to match the hash values, this gives O(1) opcode dispatch without any search loop. Each DATA block ends with a sentinel `nn` (line 395) that forces an error if no match is found. ### Two-Pass Assembly Pass 1 (lines 205–210) walks the source buffer, recording label addresses into array `l(1..99)` and computing code addresses based on instruction sizes stored in each record. Pass 2 (lines 223–262) re-walks the buffer, resolves label references, checks relative-jump range (lines 240–248), writes bytes with `POKE org+dif,...`, and prints the listing. An origin/load-address split (`dif=adr-org`) supports assembling to a different address than where code will run. ### Instruction Encoding Dispatch Operand parsing and byte generation use indirect GO TO via numeric variables set at line 804. For example, `ri`=400 parses a register, `v1`=410 parses a byte value, `v2`=470 parses a 16-bit value, `cf`=460 parses a condition flag, etc. The formatters at lines 600–616 build `m$` from parsed values and prefix bytes: - `f1` (602): single byte, optional IX/IY prefix - `f2` (604): single byte with optional prefix and displacement - `f3` (606): CB-prefix instruction with displacement - `f4` (608): prefix + opcode + 16-bit immediate - `f5` (610): opcode + 8-bit immediate - `f6` (612): opcode + zero byte (relative jump placeholder resolved in pass 2) - `f7` (614): ED-prefix instruction - `f8` (616): prefix + opcode + displacement + 8-bit immediate - `f0` (600): ED + opcode + 16-bit immediate ### Machine Code Helper Routine Lines 2000–2006 install a 19-byte Z80 routine into RAM above the BASIC system. The address is computed from system variable 23637 (PROG) offset by 5. The routine is used via `USR insert` on line 26 to perform a fast block copy when inserting new source records into the middle of `q$`, instead of doing it character-by-character in BASIC. The `RANDOMIZE last-ptr+k1` call just before it passes the byte count in the random-number seed (accessible to the machine code via system variables at 23670–23671). ### Variable Aliasing for Line Numbers At lines 804–806, most target line numbers are stored in named variables (e.g., `ri=400`, `v1=410`, `run=700`, `op=125`, `error=90`). GO TO and GO SUB then use these variables. This is both a readability aid and a standard memory optimization — storing a line number once as a variable avoids repeated literal lookups in the BASIC line table. ### Constants k0 and k1 The values 0 and 1 are stored in `k0` and `k1` respectively (set via `NOT a` / `NOT k0` at line 801). These are used pervasively as loop bounds, array indices, and boolean masks. This is a well-known Spectrum BASIC technique to avoid storing floating-point literals for frequently used small integers, saving both space and evaluation time. ### Save and Load Line 737 saves the source buffer to tape as a numeric array. Before saving, it packs `lns`, `mc`, and `last` into the first 8 bytes of `q$` using `RANDOMIZE` + `PEEK 23670/23671` to extract the 16-bit integer parts of those values and store them as characters. Line 740 reverses this on load. After assembly, line 760 saves the generated machine code with `SAVE a$ CODE adr,len`. ### Pseudo-Opcodes The assembler supports several pseudo-opcodes handled specially in pass 2: - `DEFS n` — reserves `n` bytes (advances `org`) - `DEFB n` — emits one byte - `DEFW n` — emits a 16-bit little-endian word - `DEFL Ln` — assigns a value directly to label `n` - `TEXT` — stores a text string as bytes - `TRA` and `REM` — treated as no-ops (line 1096–1099) ### Notable Anomalies - Line 1026 DATA contains `"SBC","~"` — the tilde here appears inside a string literal and is a literal character, likely intended as the letter `A` that was corrupted in entry; the SBC A,n form uses operand matching against this string. - Line 868 has `vn,402,233,f1` — this dispatches to line 402, which is inside the register-parsing subroutine at 400, skipping the main register check to handle `JP (IX)` and `JP (IY)` via the indexed-register path. - Line 32 uses `POKE scc,hi` (where `scc=23692` and `hi=255`) to reset the Spectrum’s scroll counter, preventing the “scroll?” prompt during long listings. - The `PRINT BRIGHT K1;` at line 780 uses an uppercase `K1` which is an undefined variable; it will evaluate to 0, so `BRIGHT 0` rather than the presumably intended `BRIGHT 1` — a likely entry error. ## Source Code ``` 1 CLEAR 54999: BORDER 1: PAPER 6: POKE 23609,10: LET a=2000: GO TO 801: REM spectrum assembler from Your Computer November 1983. Entered by F. Chrysler 2 DEF FN r(x,y,z$)=(CODE z$>=CODE STR$ x) AND (CODE z$<=CODE STR$ y) 3 DEF FN a(x)=PEEK x+256*PEEK (x+1) 4 DEF FN q$(x,y)=q$(ptr+x TO ptr+y) 5 DEF FN c(x)=CODE q$(ptr+x) 10 FOR x=k1 TO l-k1: LET a=a+FN c(6): LET ptr=ptr+8+FN c(5)+FN c(6): NEXT x: RETURN 20 IF l1>lns OR l1LEN q$ THEN LET z$="No more room": GO TO run 26 RANDOMIZE last-ptr+k1: LET q$(ptr TO ptr+len-k1)=p$ AND USR insert: LET ptr=ptr+LEN p$: LET mc=mc+LEN m$: LET last=last+len: LET lns=lns+k1: GO TO 24 28 LET l1=l-10: LET l2=lns: IF l1>lns-32 THEN LET l1=lns-21 29 IF l1<=k0 OR lns<=22 THEN LET l1=k1 30 PAUSE k1: LET ptr=9: LET l=l1: GO SUB 10: CLS : IF NOT lns THEN PRINT "Empty": GO TO 701 32 POKE scc,hi: LET l=FN c(k0): LET l$=("L"+STR$ l) AND l: PRINT l1;TAB 3;L$;TAB 8;FN q$(k1,4);TAB 13;: LET l=FN c(5): PRINT FN q$(8,7+l): LET ptr=ptr+8+l+FN c(6): LET l1=l1+k1: IF l1<=l2 AND INKEY$="" THEN GO TO 32 34 GO TO 701 40 IF l1lns OR l1>l2 THEN LET z$="Range error": GO TO run 42 LET l=l1: LET ptr=9: GO SUB 10: LET p1=ptr: LET l=l2-l1+2: LET a=k0: GO SUB 10: LET len=ptr-p1 44 FOR x=p1 TO last-len-31 STEP 32: LET y=x+len: LET q$(x TO x+31)=q$(y TO y+31): NEXT x: LET q$(x TO last-len)=q$(x+len TO last): LET mc=mc-a: LET last=last-len: LET lns=lns-l2+l1-k1: LET len=k0: IF z$<>"R" THEN GO TO 28 45 PRINT "Replacing ";l1;" to ";l2: LET ptr=p1: LET l=l1: IF ptrLEN q$ THEN LET z$="No more room": GO TO run 52 LET q$(last+k1 TO last+len)=p$: LET mc=mc+LEN m$: LET last=last+len: LET lns=lns+k1: GO TO 50 80 BEEP .1,k0: POKE 23658,8: INPUT "Error"' FLASH (x=1);(l$);TAB 7; FLASH (x=2);(a$);TAB 14; FLASH (x>2);(b$);" ";(c$); FLASH k0;TAB 30; LINE z$: RETURN 90 IF x=3 THEN RETURN 94 GO SUB 80: IF x>k1 THEN GO TO 104 100 LET m$="": LET x=k1: INPUT (d$)' LINE l$: IF l$="" THEN LET l1=k0: GO TO 104 102 IF CODE l$<>CODE "L" OR NOT FN r(k0,9,l$(2 TO )) THEN GO TO error 103 LET l1=VAL l$(2 TO ): IF STR$ l1<>l$(2 TO ) OR ABS (l1-50)>49 THEN GO TO error 104 LET b$="": LET c$="": LET len=k0: LET x=2: INPUT (d$)'(l$);TAB 7; LINE a$ 106 IF a$="" THEN LET p$="": RETURN 110 LET e$=a$: LET a=2*CODE e$+5*CODE e$(2)+6*CODE e$(3)+4*CODE e$(4): RESTORE a: READ t$: IF t$<>a$ THEN GO TO error 112 LET d=k0: LET n=k0: LET l2=k0: LET i=k0: READ a: IF NOT a THEN READ b,f: GO TO f 114 INPUT (d$);" 1st"'(l$);TAB 7;(a$);TAB 14; LINE b$ 115 IF a>k1 THEN INPUT (d$);TAB 15+LEN b$;"2nd"'(l$);TAB 7;(a$);TAB 14;(b$);" "; LINE c$ 116 LET a=(b$<>"")+(c$<>"") 120 LET x=3: LET i=k0: LET d=k0: LET n=k0: LET l2=k0: READ g: GO TO g 125 LET b$=b$+("," AND (c$<>""))+c$: PRINT l;TAB 3;l$;TAB 8;a$;TAB 13;b$ 126 LET p$=CHR$ l1+e$+CHR$ LEN b$+CHR$ LEN m$+CHR$ l2+b$+m$ 129 POKE 23658,8 130 RETURN 200 OPEN #2,s$: LET help=780 202 INPUT "Assemble at ";(adr);". Origin at ?"; LINE z$: LET org=adr: IF z$<>"" THEN LET org=VAL z$ 204 LET dif=adr-org: DIM l(99): LET ptr=9: CLS : PRINT BRIGHT k1;"1st Pass - Labels" 205 FOR x=k1 TO lns: LET l=FN c(k0): IF l<>k0 THEN LET l(l)=org: POKE scc,hi: PRINT "L";l;TAB 4;" = ";org," line ";x 207 IF FN q$(k1,4)="DEFS" THEN LET org=org+VAL FN q$(8,7+FN c(5)) 210 LET org=org+FN c(6): LET ptr=ptr+8+FN c(5)+FN c(6): NEXT x 220 LET org=adr-dif: LET ptr=9: PRINT ' BRIGHT k1;"2nd Pass - Assembly" 223 FOR x=k1 TO lns: LET l$="": PRINT org;: LET a$=FN q$(k1,4): LET l=FN c(7): LET l1=FN c(5): LET l2=FN c(6): LET m$=FN q$(8+l1,7+l1+l2): IF FN c(k0)<>k0 THEN LET l$="L"+STR$ FN c(k0) 224 IF org>65535 THEN LET z$="Address too large - Line "+STR$ x: GO TO run 225 IF INKEY$<>"" THEN GO TO 225 226 POKE scc,hi: IF l=hi THEN LET n=VAL FN q$(8,7+FN c(5)): LET l=k0: LET n2=INT (n/256): LET n1=n-256*n2: LET n2=n2+256*(n2=-127 AND f<=128 THEN LET a=k0: LET f=256*(f2 THEN LET z$="Label too large": LET n2=INT (l(l)/256): LET n1=l(l)-256*n2: IF n2>=k0 AND n2<=hi THEN LET a=k0: LET m$(l2-k1)=CHR$ n1: LET m$(l2)=CHR$ n2 248 IF a THEN LET z$=z$+" - Line "+STR$ x: GO TO run 250 LET z$="": FOR y=k1 TO l2: IF b$="B" THEN IF a$<>"TEXT" THEN PRINT TAB 27; BRIGHT 1;CODE m$(y);: LET v=CODE m$(y): LET v=LEN STR$ v: PRINT BRIGHT 1;" "(1 TO 4-v); 251 IF b$="H" THEN IF a$<>"TEXT" THEN LET v=CODE m$(y): LET n$=h$(v/16+.5): LET v=v-INT (v/16)*16+.5: LET n$=n$+h$(v): PRINT TAB 28; BRIGHT 1;" ";n$;" "; 255 POKE org+dif,CODE m$(y): LET org=org+k1: NEXT y: PRINT : NEXT x: LET len=org-adr+dif: PRINT '" Origin = ";adr;" Len = ";len 260 PRINT ' BRIGHT 1;"Label values" 261 FOR z=1 TO 99: IF l(z) THEN PRINT "L";z;TAB 4;" = ";l(z) 262 NEXT z 270 GO TO 750 300 READ v$,g: IF b$=v$ THEN LET s$=c$: GO SUB g: IF NOT x THEN READ b,f: GO TO f 302 READ b,f: GO TO rd 310 READ g,g1: LET s$=b$: GO SUB g: IF NOT x THEN LET s$=c$: LET x=3: GO SUB g1: IF NOT x THEN READ b,f: GO TO f 312 READ b,f: GO TO rd 320 READ g: IF c$="" THEN LET s$=b$: GO SUB g: IF NOT x THEN READ b,f: GO TO f 322 READ b,f: GO TO rd 330 READ v$: IF (b$+c$)=v$ THEN READ b,f: GO TO f 332 READ b,f: GO TO rd 340 READ g,v$: IF c$=v$ THEN LET s$=b$: GO SUB g: IF NOT x THEN READ b,f: GO TO f 342 READ b,f: GO TO rd 350 RESTORE 817+((LEN b$-5) AND (LEN b$<5)): READ s$: GO TO rd 360 READ g,g1: LET s$=b$: GO SUB g: IF NOT x THEN LET r1=r: LET s$=c$: LET x=3: GO SUB g1: IF NOT x AND (r1<>6 OR r<>6) THEN READ b,f: GO TO f 362 READ b,f: GO TO rd 370 LET x=4: LET org=VAL b$: LET l2=hi: LET m$="": GO TO op 372 LET x=4: LET n=VAL b$: LET l2=hi: LET m$=" ": GO TO op 374 LET x=4: LET n=VAL b$: LET l2=hi: LET m$=" ": GO TO op 376 LET m$=b$: GO TO op 378 LET x=4: IF l1>k0 AND l1<100 THEN LET n=VAL b$: LET l2=hi: LET m$="": GO TO op 379 LET x=k1: LET z$="No label": GO TO error 395 LET x=4: GO TO error 400 LET r=(s$="B")+(2 AND s$="C")+(3 AND s$="D")+(4 AND s$="E")+(5 AND s$="H")+(6 AND s$="L")+(7 AND s$="(HL)")+(8 AND s$="A"): IF r THEN LET r=r-k1: LET x=k0: RETURN 402 IF CODE s$=CODE "(" THEN LET i=221*(s$(2 TO 3)="IX")+253*(s$(2 TO 3)="IY"): IF i THEN LET r=6: LET d=VAL s$: IF d>=-128 AND d<=127 THEN LET d=d+256*(d=k0 AND n<=56 AND 8*INT (n/8)=n THEN LET x=k0: RETURN 481 RETURN 490 IF FN r(k0,7,b$) AND LEN b$=k1 THEN LET r1=VAL b$: LET x=k0: RETURN 491 RETURN 500 IF FN r(k0,2,b$) AND LEN b$=k1 THEN LET n=VAL b$: LET n=n+(n>k0): LET x=k0: RETURN 501 RETURN 510 GO SUB cf: IF NOT x AND r<4 THEN LET x=k0: RETURN 511 LET x=3: RETURN 520 IF CODE s$=CODE "(" THEN IF CODE s$(LEN s$)=CODE ")" THEN LET s$=s$(2 TO LEN s$-k1): GO TO v2 521 RETURN 530 IF CODE s$=CODE "(" THEN IF CODE s$(LEN s$)=CODE ")" THEN LET s$=s$(2 TO LEN s$-k1): GO TO v1 531 RETURN 600 LET n2=INT (n/256): LET n1=n-256*n2: LET m$=CHR$ 237+CHR$ b+CHR$ n1+CHR$ n2: GO TO op 602 LET m$=((CHR$ i) AND i)+CHR$ b: GO TO op 604 LET m$=((CHR$ i) AND i)+CHR$ b+((CHR$ d) AND i): GO TO op 606 LET m$=((CHR$ i) AND i)+CHR$ 203+((CHR$ d) AND i)+CHR$ b: GO TO op 608 LET n2=INT (n/256): LET n1=n-256*n2: LET m$=((CHR$ i) AND i)+CHR$ b+CHR$ n1+CHR$ n2: GO TO op 610 LET m$=CHR$ b+CHR$ n: GO TO op 612 LET m$=CHR$ b+CHR$ 0: GO TO op 614 LET m$=CHR$ 237+CHR$ b: GO TO op 616 LET m$=((CHR$ i) AND i)+CHR$ b+((CHR$ d) AND i)+CHR$ n: GO TO op 620 STOP 699 GO SUB 80: GO TO 701 700 BEEP .1,30: POKE 23658,8: INPUT "Error"'(z$);TAB 30; LINE z$ 701 OPEN #2,"S": INPUT AT k0,k0;"Append Insert Delete Replace"'"Print Save Load Control "; LINE z$ 705 IF z$="I" THEN INPUT "Before ";l1: GO TO 20 710 IF z$="A" THEN PRINT BRIGHT k1;"Appending": GO TO 50 715 IF z$="D" THEN INPUT "From ";l1;" to ";l2: GO TO 40 717 IF z$="R" THEN INPUT "Replace ";l1;" to ";l2: GO TO 40 719 IF z$="PR" THEN OPEN #2,"P" 720 IF z$="P" OR z$="PR" AND lns<23 THEN LET l1=k1: LET l2=lns: GO TO 30 725 IF z$="P" OR z$="PR" THEN INPUT "From ";l1: LET l2=lns: GO TO 30 730 IF z$="C" THEN GO TO 780 737 IF z$="S" THEN INPUT "File name ";a$: RANDOMIZE lns: LET q$(k1)=CHR$ PEEK 23670: LET q$(2)=CHR$ PEEK 23671: RANDOMIZE mc: LET q$(3)=CHR$ PEEK 23670: LET q$(4)=CHR$ PEEK 23671: LET q$(5 TO 8)=STR$ last: SAVE a$ DATA q$(): PRINT FLASH k1;"Verify": VERIFY a$ DATA q$() 740 IF z$="L" THEN INPUT "File name ";a$: LOAD a$ DATA q$(): LET a$="": LET lns=CODE q$(1)+256*CODE q$(2): LET mc=CODE q$(3)+256*CODE q$(4): LET last=VAL q$(5 TO 8): GO TO 780 745 GO TO 701 750 OPEN #2,"S": INPUT "Save Run Control Edit "; LINE z$ 755 IF z$="E" THEN LET l1=k1: LET l2=lns: GO TO 30 758 IF z$="C" THEN GO TO 780 760 IF z$="S" AND len THEN INPUT "Name of Mcode ";a$: SAVE a$CODE adr,len 765 IF z$="R" AND NOT dif AND len THEN INPUT "Origin= ";(adr);". Enter at "; LINE a$: LET org=adr: IF a$<>"" THEN LET org=VAL a$ 766 IF z$="R" AND NOT dif AND len THEN CLS : PRINT #2;AT k0,k0;: RANDOMIZE USR org 770 GO TO 750 780 CLS : PRINT BRIGHT K1;" ZX SPECTRUM EDITOR/ASSEMBLER DAVID HAWKINS FEB 1983 "''' 781 PRINT "TEXT FILE"''" LENGTH = ";LEN q$'" USED = ";last'" UNUSED = ";LEN q$-last'" LINES = ";lns'" MCODE = ";mc''"SPARE"''" LENGTH = ";FN a(23730)-FN a(23653)''"CODE"''" START = ";adr'" LENGTH = ";len 785 INPUT "EDIT ASSEMBLE CODE RESTART "; LINE z$ 786 IF z$="C" THEN GO TO 750 788 IF z$="R" THEN GO TO 800 790 IF z$="A" THEN GO TO 795 792 IF z$="E" THEN LET l1=k1: LET l2=lns: GO TO 30 793 IF z$="QUIT" THEN STOP 794 GO TO 785 795 INPUT "Screen or Printer "; LINE s$: IF s$<>"S" AND s$<>"P" THEN GO TO 795 796 INPUT "Bytes or Nobytes "; LINE b$: IF b$<>"B" AND b$<>"N" AND b$<>"H" THEN GO TO 796 797 GO TO 200 800 INPUT AT 0,0;"File Length = ";a;" Code Start = ";z: RANDOMIZE a: CLEAR z-1: LET a=FN a(23670) 801 DIM q$(a): LET k0=NOT a: LET k1=NOT k0: GO SUB 2000: LET a$="": LET b$="": LET c$="": LET l$="": LET lns=k0: LET last=8: LET mc=k0: LET scc=23692: LET hi=255: LET dif=k0: LET h$="0123456789ABCDEF" 802 LET adr=FN a(23730)+1: LET len=k0: POKE 23658,8: DIM e$(4): DIM l(99): LET ptr=9: LET rd=120: LET op=125: LET error=90: LET help=699: LET org=adr: LET len=k0 804 LET r1=k0: LET ps=370: LET ldr=360: LET load=350: LET bv1=530: LET bv=520: LET ix=k0: LET iy=k0: LET sv=300: LET vv=310: LET vn=320: LET ss=330: LET vs=340: LET nn=395: LET ri=400: LET v1=410: LET da=420: LET ds=430: LET di=440: LET dd=450: LET cf=460: LET v2=470: LET ra=480: LET bn=490: LET im=500: LET cs=510 806 LET run=700: LET f0=600: LET f1=602: LET f2=604: LET f3=606: LET f4=608: LET f5=610: LET f6=612: LET f7=614: LET f8=616: LET d$="Label Opcode": GO TO 780 812 DATA "LD",2,load 813 DATA "",ldr,ri,ri,64+8*r1+r,f2,vv,ri,v1,6+8*r,f8,sv,"A",bv,58,f4,ss,"A(BC)",10,f1,ss,"A(DE)",26,f1,ss,"AI",87,f7,ss,"AR",95,f7,ss,"IA",71,f7,ss,"RA",79,f7,nn 814 DATA "",sv,"BC",bv,75,f0,sv,"DE",bv,91,f0,vv,di,bv,42,f4,vv,ds,v2,1+16*r,f4,sv,"HL",v2,33,f4,sv,"SP",bv,123,f0,sv,"SP",di,249,f1,nn 817 DATA "",ss,"(BC)A",2,f1,ss,"(DE)A",18,f1,ldr,ri,ri,64+8*r1+r,f2,vv,ri,v1,6+8*r,f8,vs,bv,"A",50,f4,vv,bv,di,34,f4,vv,bv,ds,67+16*r,f0,nn 821 DATA "DI",k0,243,f1 823 DATA "EI",k0,251,f1 851 DATA "IM",k1,vn,im,70+8*n,f7,nn 854 DATA "CP",k1,vn,ri,184+r,f2,vn,v1,254,f5,nn 856 DATA "IN",2,sv,"A",bv1,219,f5,vs,ri,"(C)",64+8*r,f7,nn 864 DATA "RL",k1,vn,ri,16+r,f3,nn 868 DATA "JP",2,vv,cf,v2,194+8*r,f4,ss,"(HL)",233,f1,vn,402,233,f1,vn,v2,195,f4,nn 878 DATA "JR",2,vv,cs,v2,32+8*r,f6,vn,v2,24,f6,nn 888 DATA "OR",k1,vn,ri,176+r,f2,vn,v1,246,f5,nn 894 DATA "RR",k1,vn,ri,24+r,f3,nn 898 DATA "EX",2,sv,"(SP)",di,227,f1,ss,"AFAF'",8,f1,ss,"DEHL",235,f1,nn 979 DATA "DAA",k0,39,f1 1000 DATA "ADC",2,sv,"A",ri,136+r,f2,sv,"A",v1,206,f5,sv,"HL",dd,74+16*r,f7,nn 1006 DATA "ADD",2,sv,"A",ri,128+r,f2,sv,"A",v1,198,f5,vv,di,dd,9+16*r,f1,nn 1011 DATA "DEC",k1,vn,ri,5+8*r,f2,vn,ds,11+16*r,f1,nn 1017 DATA "CCF",k0,63,f1 1026 DATA "SBC",2,sv,"A",ri,152+r,f2,sv,"~",v1,222,f5,sv,"HL",dd,66+16*r,f7,nn 1028 DATA "LDD",k0,168,f7 1049 DATA "SCF",k0,55,f1 1055 DATA "NEG",k0,68,f7 1056 DATA "AND",k1,vn,ri,160+r,f2,vn,v1,230,f5,nn 1058 DATA "LDI",k0,160,f7 1062 DATA "RLA",k0,23,f1 1064 DATA "SLA",k1,vn,ri,32+r,f3,nn 1066 DATA "INC",k1,vn,ri,4+8*r,f2,vn,ds,3+16*r,f1,nn 1070 DATA "CPD",k0,169,f7 1072 DATA "IND",k0,170,f7 1074 DATA "RLC",k1,vn,ri,r,f3,nn 1080 DATA "RLD",k0,111,f7 1092 DATA "RRA",k0,31,f1 1094 DATA "SRA",k1,vn,ri,40+r,f3,nn 1096 DATA "TRA",k1,op 1099 DATA "REM",k1,op 1100 DATA "CPI",k0,161,f7 1102 DATA "INI",k0,162,f7 1104 DATA "RRC",k1,vn,ri,8+r,f3,nn 1110 DATA "RRD",k0,103,f7 1115 DATA "SUB",k1,vn,ri,144+r,f2,vn,v1,214,f5,nn 1118 DATA "CPL",k0,47,f1 1129 DATA "BIT",2,vv,bn,ri,64+8*r1+r,f3,nn 1135 DATA "RES",2,vv,bn,ri,128+8*r1+r,f3,nn 1141 DATA "RET",k1,ss,"",201,f1,vn,cf,192+8*r,f1,nn 1143 DATA "SET",2,vv,bn,ri,192+8*r1+r,f3,nn 1159 DATA "NOP",k0,k0,f1 1160 DATA "SRL",k1,vn,ri,56+r,f3,nn 1163 DATA "POP",k1,vn,da,193+16*r,f1,nn 1165 DATA "DEFB",k1,ps+2 1191 DATA "XOR",k1,vn,ri,168+r,f2,vn,v1,238,f5,nn 1205 DATA "DEFL",k1,ps+8 1206 DATA "RLCA",k0,7,f1 1211 DATA "RST",k1,vn,ra,199+n,f1,nn 1215 DATA "OUT",2,vs,bv1,"A",211,f5,sv,"(C)",ri,65+8*r,f7,nn 1219 DATA "CALL",2,vv,cf,v2,196+8*r,f4,vn,v2,205,f4,nn 1228 DATA "LDDR",k0,184,f7 1233 DATA "DEFS",k1,ps 1234 DATA "EXX",k0,217,f1 1236 DATA "RRCA",k0,15,f1 1249 DATA "DEFW",k1,ps+4 1258 DATA "LDIR",k0,176,f7 1261 DATA "HALT",k0,118,f1 1270 DATA "CPDR",k0,185,f7 1272 DATA "INDR",k0,186,f7 1300 DATA "CPIR",k0,177,f7 1302 DATA "INIR",k0,178,f7 1305 DATA "RETI",k0,77,f7 1314 DATA "OTDR",k0,187,f7 1325 DATA "RETN",k0,69,f7 1334 DATA "DJNZ",k1,vn,v2,16,f6,nn 1344 DATA "OTIR",k0,179,f7 1359 DATA "OUTD",k0,171,f7 1371 DATA "PUSH",k1,vn,da,197+16*r,f1,nn 1377 DATA "TEXT",k1,ps+6 1379 DATA "OUTI",k0,163,f7 2000 LET insert=FN a(23637)+5 2001 REM GO SUB Kv\\*M\\+ FOR *r\\ FOR GO SUB LN <>x 2004 RESTORE 2006: FOR z=insert TO insert+18: READ a: POKE z,a: NEXT z 2005 RETURN 2006 DATA 237,75,118,92,42,77,92,9,43,235,42,114,92,25,235,237,184,3,201 9998 CLEAR : SAVE "DEV-Assem" LINE 1: BEEP .2,0: PRINT FLASH 1;"VERIFY": VERIFY "": BEEP .2,0: PRINT "OK" ```