This program is a Z80 assembler written entirely in BASIC, targeting the T/S 2068 and capable of assembling Z80 source code entered interactively or merged from tape. It supports the full Z80 instruction set including ED-prefix and CB-prefix opcodes, IX/IY indexed addressing with displacement, conditional jumps and calls, pseudo-ops (ORG, EQU, DEFB, DEFW), a symbol table with forward-reference resolution, and optional hard-copy output. The assembler uses a table-driven architecture: operand types are encoded as numeric class codes (e.g., register class 1–7, indirect class with parentheses), and instruction dispatch is handled by a two-pass table scan through the DATA statements at lines 2000–2200. An embedded REM block at lines 10–70 contains commented Z80 assembly source for a short machine-code routine that prints “BOB GILDER” via ROM calls, illustrating the tool’s own use case.
Adapted from the ZX Spectrum Assembler in Phipps Associates’ Machine Code Tools.
Program Analysis
Program Structure
The assembler is organized into several well-defined regions:
- Lines 10–70: Embedded REM block containing commented Z80 assembly source (the program’s own demonstration).
- Lines 1000–1140: Initialization — function definitions, symbol table allocation, display setup, hard-copy and auto-scan options.
- Lines 1200–1990: Main assembly loop — line input, tokenization, operand classification, instruction lookup, code emission, symbol definition.
- Lines 2000–2200: DATA tables encoding the Z80 instruction set in a structured, table-driven format.
- Lines 5000–5210: End-of-assembly pass — symbol table listing, unresolved forward-reference patching, error summary.
- Lines 7200–7900: Subroutines — undefined symbol handling, line printing, operand classification, offset calculation, auto-scan source locator, symbol lookup.
- Lines 8300–8900: Table search routines and numeric/hex/symbol value resolution.
- Lines 9000–9140: Keyboard input (with uppercase normalization), hex formatter.
- Lines 9900–9922: Register/condition name DATA tables and forward-reference relocation DATA.
Function Definitions
| Function | Purpose |
|---|---|
FN a(x$) | Returns true if x$ is an uppercase letter A–Z |
FN n(x$) | Returns true if x$ is a digit 0–9 |
FN s$(x) | Extracts the x-th scanned token from a$ using the x() position array |
FN h(x) | High byte of a 16-bit value (INT(x/256)) |
FN L(x) | Low byte of a 16-bit value (x mod 256) |
FN j() | True if current mnemonic is JP, JR, CALL, or RET (jump-class) |
FN v(x$) | Extracts 16-bit address stored in bytes 7–8 of a symbol table entry |
FN i(x) | Reads a 16-bit little-endian word from memory at address x |
FN r() | Computes relative jump displacement: di - vdef*(add+2) |
Symbol Table Design
The symbol table is a DIMensioned string array s$() of 8-character entries. The first entry s$(1) stores the current symbol count as CHR$ of the count value. Entries 2 through ns+1 (64 entries) hold defined labels; entries ns+3 upward (another 64 slots) hold forward-reference (unresolved) entries. Each entry stores up to 6 characters of the label name, followed by 2 bytes encoding the associated address in little-endian form using CHR$ FN L(v) + CHR$ FN h(v). The FN v(s$(y)) function recovers this address by reading CODE x$(7) + 256*CODE x$(8).
Operand Classification System
After tokenization, each operand string is classified into a numeric type stored in both t() (integer) and t$() (character). The classification table at line 9900 lists 15 register/condition names; the lookup index becomes the operand class. The string "111111112222222070000005515011" at line 7460 is a compact encoding mapping register indices to operand type codes (1=8-bit reg, 2=16-bit reg pair, etc.). Indirect addressing (parenthesized operands) shifts the type classification by 15 positions in this string. IX/IY with displacement are detected at index 13/14, setting the e flag and storing the displacement in dis.
Table-Driven Instruction Encoding
Each DATA record for an instruction has the form: a scan-code string (combining operand type digits and mnemonic), a validity expression (evaluated with VAL), a byte count, and then byte-value expressions. The two-level search uses GO SUB 8300 to match the mnemonic and GO SUB 8400 to match the full operand-type signature. Byte values are themselves BASIC expressions (e.g., "64+t(1)*8+t(2)", "198+n*8") evaluated at emit time with VAL x$, making a compact and general encoding scheme.
The variable n$ at line 1500 concatenates the two operand type characters with the mnemonic to form the composite key used in the second-level search. The DATA sections are organized by operand-count class: lines 2010–2011 for zero-operand single-byte, 2020–2031 for zero-operand multi-byte, 2040–2059 for single-operand, 2060–2085 for one/two-operand arithmetic, and 2100–2200 for conditional forms.
Forward Reference Resolution
When an operand cannot be resolved at assembly time, the symbol name is stored in s$(ns+2) and the vdef flag is set. The address of the instruction needing patching is added to the unresolved table (lines 7200–7230). At end-of-assembly (lines 5020–5100), each unresolved entry is looked up in the symbol table; if found, the relocation DATA at lines 9920–9922 is used to determine how many bytes to patch and what values to write. Three relocation cases are handled: relative jumps (case 0), ED/DD/FD prefixed instructions (case 1), and absolute 16-bit addresses (case 2), distinguished by inspecting the first opcode byte at the patch address.
Auto-Scan Mode
The auto-scan feature (lines 7800–7880 and 7700–7780) locates BASIC source lines in memory by searching the BASIC program area using the system variables at addresses 23635 (PROG) and 23627 (VARS), walking line headers to find a line beginning with token 234 (the keyword encoding checked at line 7840) and the character code 40 at offset 5. This allows the assembler to read its own source program’s REM blocks or embedded assembly source directly from the BASIC line store without tape or keyboard input.
Hex Formatter
Lines 9100–9140 implement a hex formatter that converts an integer h into a 4-digit (or 2-digit) hex string h$ by repeated modulo-16 decomposition. Digits above 9 are adjusted by adding 7 to the character code to produce A–F, a standard Sinclair BASIC hex-formatting idiom.
Notable Techniques
- The scalar variable
jis initialized to 1 and used pervasively as a literal 1 substitute, saving tokenized bytes in the program store. NOT jevaluates to 0 andNOT NOT jto 1, used to initialize boolean flags compactly.VAL "number"is used extensively in GO TO, GO SUB, and numeric contexts as a memory optimization to store numbers as strings rather than 5-byte floating-point literals.- Validity expressions in the DATA tables (e.g.,
"vdef AND ds<=56") are evaluated viaVAL c$at runtime, giving a data-driven conditional assembly check without additional BASIC code. - Byte-value expressions in DATA (e.g.,
"192+t(1)*8") are similarlyVAL-evaluated, encoding the Z80 opcode arithmetic directly in the table strings. - The
PRINT #hc;idiom sends output to streamhc, which is 0 (screen only), 1 (printer only), or 2 (both), depending on the hard-copy option selected at startup. - Line 1095 uses
CHR$ NOT j(i.e.,CHR$ 0) to initialize the symbol count byte ins$(1).
Embedded Demo Source
The REM block at lines 10–70, delimited by ( and ) markers, contains Z80 assembly source that, when assembled, produces a routine at address 65367 that calls ROM routine 1601H to select channel 2, then prints the string “BOB GILDER” character by character using RST 10H. This serves as both a usage example and a signature for the program’s author.
Potential Anomalies
- The
FN r()displacement formula usesvdefas a multiplier: when a symbol is unresolved,vdefis non-zero (1), so the displacement is computed; when resolved at the second pass, this may produce an incorrect relative value on the first pass, which is corrected during forward-reference patching. - Error code 99 at line 1925 is used for a full symbol table, while error code 98 at line 7210 covers a full unresolved table; error code 9 (line 1630) flags an unrecognized instruction, and code 6 (line 8510) flags an out-of-range value.
- The auto-scan search at line 7840 checks
PEEK(x+4)=234; the meaning of token 234 depends on the ROM token set and is used here as a heuristic marker rather than a portable line-structure field.
Content
Source Code
10 REM (
20 REM org 65367!ld a,2!call 1601H!ld a,12H!rst 10H!ld a,1!rst 10H
30 REM ld a,42H!rst 10H!ld a,4fH!rst 10H!ld a,42H!rst 10H
40 REM ld a,20H!rst 10H!ld a,47H!rst 10H!ld a,49H!rst 10H!ld a,4cH!rst 10H
50 REM ld a,44H!rst 10H!ld a,45H!rst 10H!ld a,52H!rst 10H!ld a,20H!rst 10H
60 REM ret
70 REM )
1000 REM 2068 ASSEMBLER
1002 REM ZXASM 48K extension
1005 LET j=VAL "1": IF PEEK VAL "23731">VAL "127" THEN GO SUB VAL "7900"
1010 LET ns=64: LET nu=64
1015 CLS : PRINT " *** T/S 2068 ASSEMBLER *** ": PRINT '"RAM available:";(PEEK 23733-63)/4;"K"'"RAMTOP value : ";: LET h=FN i(23730): GO SUB 9100: PRINT h;" (";h$;"H)"
1020 DEF FN a(x$)=(x$>="A" AND x$<="Z")
1030 DEF FN n(x$)=(x$>="0" AND x$<="9")
1035 DEF FN s$(x)=a$(x(x,j)+j TO x(x,2))
1040 DEF FN h(x)=INT (x/256)
1050 DEF FN L(x)=x-256*FN h(x)
1060 DEF FN j()=(m$="JP" OR m$="CALL" OR m$="RET" OR m$="JR")
1070 DEF FN v(x$)=CODE x$(7)+256*CODE x$(8)
1080 DEF FN i(x)=PEEK x+256*PEEK (x+j)
1085 DEF FN r()=di-vdef*(add+2)
1090 DIM s$(ns+nu+j+j,VAL "8"): DIM L$(VAL "6"): DIM t$(VAL "2")
1095 LET s$(j)=CHR$ NOT j
1100 LET u=NOT j: LET er=u: LET ed=VAL "237"
1110 LET m$="HARD COPY?": GO SUB 9000: LET hc=j+j+(CHR$ CODE a$="Y")
1120 LET m$="Auto scan?": GO SUB 9000: LET auto=(CHR$ CODE a$="Y"): IF auto THEN LET m$="Merge source from tape?": GO SUB 9000: IF CHR$ CODE a$="Y" THEN INPUT "Enter tape name:"; LINE a$: CLS : PRINT AT 8,2;"START TAPE THEN PRESS A KEY": PAUSE 4e4: CLS : MERGE a$
1125 IF auto THEN GO SUB 7800
1130 LET add=FN i(VAL "23730")+VAL "1": REM get default address
1140 CLS : PRINT #hc;"ADDR HEX OP OPERANDS "
1200 LET e=NOT j: LET vdef=j: LET ds=e: LET dd=e: LET ec=e: LET b=e: LET w=e
1210 LET h=add: GO SUB 9100: LET m$=h$: GO SUB 7700: IF end THEN GO TO VAL "5000"
1220 LET m$=""
1230 DIM t(2): DIM x(4,2): LET t=NOT j: LET p=j: LET t$="00"
1240 FOR x=j TO LEN a$: REM now scan input line
1245 IF a$(x)=";" THEN GO TO 1300: REM ignore comments
1250 IF t<>(a$(x)<>" " AND a$(x)<>",") THEN LET x(p,t+j)=x-j: LET p=p+t: LET t=NOT t: IF p>4 THEN GO TO 1310: REM mark word ends
1260 NEXT x
1300 IF x(p,j) OR p=j THEN LET x(p,j+j)=x-j
1310 LET bx=(FN s$(j)(LEN FN s$(j))=":"): REM check for symbol
1320 LET m$=FN s$(j+bx): REM get instruction
1400 LET jump=FN j(): REM is this a JP/JR/CALL?
1410 FOR t=j TO j+j: LET x$=FN s$(j+t+bx): GO SUB 7400: NEXT t: REM determine op classes
1500 LET n$=t$+m$: REM create scanning code
1510 LET f1=(LEN FN s$(bx+2)<>0): LET f2=(LEN FN s$(bx+3)<>0): IF f1 THEN GO TO 1600: REM find how many ops
1520 IF m$="" THEN GO TO 1900: REM no instruction
1530 FOR b=j TO j+j: LET i=VAL "2010+b*10": GO SUB 8300: IF NOT x THEN NEXT b: REM vet no op type
1550 GO TO 1630
1600 LET i=VAL "2060+f2*20": LET b=NOT j: REM vet 1/2 op types
1610 GO SUB 8300: IF NOT x+f2 THEN LET i=2070: GO SUB 8300
1615 IF x THEN GO TO 1650
1620 RESTORE VAL "2000+40*(f2=0)": GO SUB 8400: IF x THEN GO TO 1800
1630 IF NOT x THEN LET ec=VAL "9": REM invalid instruction
1640 GO TO 1800
1650 LET n=x-j: RESTORE i+j: LET n$=t$: GO SUB 8400: IF NOT x THEN LET ec=VAL "9"
1800 IF ec THEN GO TO 1960: REM don't output if error
1820 IF m$="ORG" THEN LET add=di: LET h=di: GO SUB 9100: REM check for pseudo-op
1830 IF e THEN POKE add,dd: IF e=j+j THEN POKE add+j+j,dis: REM echeck if IX/IY class output displacement
1840 FOR x=0 TO b-j: READ x$: POKE add+x+(e<>0)+x*(e=2),VAL x$: NEXT x: REM output machine code
1900 IF NOT vdef THEN GO SUB 7200: REM undefined symbol?
1910 IF NOT bx OR ec THEN GO TO 1960: REM check for label
1920 LET L$=FN s$(bx)( TO LEN FN s$(bx)-j): GO SUB 7600: IF v THEN LET ec=2: GO TO 1960: REM does it already exist?
1925 IF s=ns+j THEN LET ec=VAL "99": GO TO 1960: REM full table
1930 LET v=add: IF m$="EQU" THEN LET v=di: REM re-equate
1940 LET s$(s)=L$: LET s$(s,7 TO )=CHR$ FN L(v)+CHR$ FN h(v)
1950 LET s$(j)=CHR$ (s-j): REM update symbol count
1960 GO SUB 7300: IF ec THEN LET er=er+j: GO TO VAL "1200": REM print line
1970 LET add=add+b+e: REM update address
1990 GO TO 1200: REM await new input
2000 DATA "11LD","1","1","64+t(1)*8+t(2)"
2001 DATA "13LD","vdef","2","t(1)*8+6","ds"
2002 DATA "14LD","t(1)=7","3","58","ds","dh"
2003 DATA "15LD","(t(1)=7)*(t(2)<2)","1","t(2)*16+10"
2004 DATA "23LD","t(1)<>6","3","t(1)*16+1","ds","dh"
2005 DATA "24LD","t(1)=2","3","42","ds","dh"
2006 DATA "24LD","t(1)<4","4","ed","75+t(1)*16","ds","dh"
2007 DATA "41LD","t(2)=7","3","50","ds","dh"
2008 DATA "42LD","t(2)=2","3","34","ds","dh"
2009 DATA "42LD","t(2)<4","4","ed","67+t(2)*16","ds","dh"
2010 DATA "51LD","(t(2)=7)*(t(1)<2)","1","t(1)*16+2"
2011 DATA "99","","2100"
2020 DATA "RET","201","NOP","0","RLCA","7","RRCA","15","RLA","23","RRA","31","DAA","39","CPL","47","SCF","55","CCF","63","HALT","118","EXX","217","DI","243","EI","251","99",""
2030 DATA "NEG","ED","68","RETN","ED","69","RETI","ED","77","RRD","ED","103","RLD","ED","111","LDI","ED","160","LDIR","ED","176","LDD","ED","168","LDDR","ED","184","CPD","ED","169","CPDR","ED","185","CPI","ED","161","CPIR","ED","177"
2031 DATA "INI","ED","162","INIR","ED","178","IND","ED","170","INDR","ED","186","OUTI","ED","163","OTIR","ED","179","OUTD","ED","171","OTDR","ED","187","99","",""
2040 DATA "30JR","ABS FN r()<128","2","24","FN r()"
2041 DATA "10INC","1","1","4+t(1)*8"
2042 DATA "20INC","t(1)<>4","1","3+t(1)*16"
2043 DATA "10DEC","1","1","5+t(1)*8"
2044 DATA "20DEC","t(1)<>4","1","11+t(1)*16"
2045 DATA "30DJNZ","ABS FN r()<128","2","16","FN r()"
2046 DATA "60RET","1","1","192+t(1)*8"
2047 DATA "20POP","t(1)<>3","1","193+t(1)*16-16*(t(1)=4)"
2048 DATA "20PUSH","t(1)<>3","1","197+t(1)*16-16*(t(1)=4)"
2049 DATA "30RST","vdef AND ds<=56","1","199+INT (ds/8)*8"
2050 DATA "10JP","t(1)=6","1","233"
2051 DATA "30IM","vdef*(ds<3)*(ds>=0)","2","ed","70+16*(ds=1)+24*(ds=2)"
2052 DATA "30JP","1","3","195","ds","dh"
2053 DATA "30CALL","1","3","205","ds","dh"
2054 DATA "30DEFB","vdef","1","ds"
2055 DATA "30DEFW","vdef","2","ds","dh"
2056 DATA "30ORG","vdef","0"
2057 DATA "30EQU","vdef AND bx","0"
2059 DATA "99","","0"
2060 DATA "","","SUB","","AND","XOR","OR","CP","99"
2061 DATA "10","1","1","128+n*8+t(1)"
2062 DATA "30","vdef","2","198+n*8","ds"
2063 DATA "99","","0"
2070 DATA "RLC","RRC","RL","RR","SLA","SRA","","SRL","99"
2071 DATA "10","1","2","203","n*8+t(1)"
2072 DATA "99","","0"
2080 DATA "ADD","ADC","","SBC","99"
2081 DATA "11","t(1)=7","1","128+n*8+t(2)"
2082 DATA "13","t(1)=7","2","198+n*8","ds"
2083 DATA "22","(t(1)=2)*(t(2)<>4)*(n=0)","1","9+t(2)*16"
2084 DATA "22","(t(1)=2)*(t(2)<>4)*(n<>0)","2","ed","78-n*4+t(2)*16"
2085 DATA "99","","0"
2100 DATA "63JP","1","3","194+t(1)*8","ds","dh"
2101 DATA "63JR","t(1)<4 AND ABS FN r()<128","2","32+t(1)*8","FN r()"
2102 DATA "22EX","(t(1)=4)*(t(2)=4)","1","8"
2103 DATA "22EX","(t(1)=1)*(t(2)=2)","1","235"
2104 DATA "52EX","(t(1)=3)*(t(2)=2)","1","227"
2112 DATA "31BIT","vdef AND ds<8","2","203","64+ds*8+t(2)"
2113 DATA "31RES","vdef AND ds<8","2","203","128+ds*8+t(2)"
2114 DATA "31SET","vdef AND ds<8","2","203","192+ds*8+t(2)"
2117 DATA "63CALL","1","3","196+t(1)*8","ds","dh"
2120 DATA "14IN","vdef AND t(1)=7","2","219","ds"
2121 DATA "41OUT","vdef AND t(2)=7","2","211","ds"
2122 DATA "17IN","t(1)<>6","2","ed","64+t(1)*8"
2123 DATA "71OUT","t(2)<>6","2","ed","65+t(2)*8"
2200 DATA "99","","0"
2201 REM end of program
5000 IF CODE s$(j) THEN PRINT #hc''"Symbols:"': FOR y=VAL "2" TO VAL "CODE s$(1)+1": LET h=FN v(s$(y)): GO SUB 9100: PRINT #hc;TAB VAL "((y-2)*16+1)";s$(y, TO 6);" ";h$;: NEXT y: REM list symbol table
5010 LET n=NOT j: REM scan unresolved table
5020 FOR t=ns+3 TO ns+2+u: LET add=FN v(s$(t)): LET c=PEEK add: LET L$=s$(t): GO SUB 7600: IF v THEN GO TO 5050: REM does it exist?
5030 IF NOT n THEN PRINT #hc''"Unresolved:"
5040 LET n=n+j: LET h=add: GO SUB 9100: PRINT #hc;" ";L$;" ";h$: GO TO 5100: REM no-print it
5050 RESTORE 9920: LET di=FN i(add+j): LET ds=FN L(di): LET di=VAL "di-65536*(di>32767)": REM determine type
5055 LET ds=VAL "ds-256*(ds>127)"
5060 READ c$,a$,x$: IF NOT VAL c$ THEN FOR x=j TO VAL x$: READ x$: NEXT x: GO TO 5060
5070 FOR x=j TO VAL a$: READ y$: POKE FN v(s$(t))+VAL x$+x-j,VAL y$: NEXT x: REM relocate output
5100 NEXT t
5200 IF er+n THEN PRINT #hc'er+n;"Error(s)": REM any errors?
5210 GO TO 9999
7200 REM undefined
7210 LET u=u+j: IF u>nu THEN LET ec=VAL "98": RETURN
7220 LET s$(ns+u+j+j)=s$(ns+j+j, TO 6)+CHR$ FN L(add)+CHR$ FN h(add)
7230 RETURN
7300 REM print detail line
7310 IF ec THEN PRINT #hc;h$;" "; INVERSE j;"ERROR ";ec; INVERSE NOT j;TAB 14;a$: RETURN
7320 IF bx THEN PRINT #hc;h$;TAB VAL "13";FN s$(j)
7330 IF m$="" THEN RETURN : REM no mnemonic entered
7340 PRINT #hc;h$; INVERSE j;"*" AND (NOT vdef); INVERSE 0;TAB 5;: FOR y=0 TO b+e-j: LET h=PEEK (add+y): GO SUB 9120: PRINT #hc;h$;: NEXT y
7350 PRINT #hc;TAB 14;m$;TAB 19;FN s$(j+j+bx);"," AND f2;FN s$(3+bx)
7360 RETURN
7400 REM check type classify operands
7405 LET x=LEN x$: IF NOT x THEN RETURN
7410 LET ix=(x$(j)="("): IF ix THEN LET x$=x$(2 TO LEN x$-j)
7415 GO SUB 7500
7420 RESTORE 9900+jump: READ n: FOR x=0 TO n-j: READ c$: IF x$=c$ THEN GO TO 7450
7425 NEXT x
7430 LET t$(t)=("3" AND (NOT ix))+("4" AND ix)
7440 GO SUB 8500: LET di=a+w: LET dh=FN h(di): LET ds=FN L(di): RETURN
7450 LET t(t)=x: IF jump AND (NOT ix) THEN LET t$(t)="6": RETURN
7460 LET t$(t)="111111112222222070000005515011"(ix*15+x+j)
7470 IF x>=13 THEN LET e=j+ix-jump: LET dd=VAL "dd+(dd=0)*(221+32*(x=14))": LET dis=w: LET x=10
7475 IF x>7 THEN LET t(t)=x-8
7480 IF ix AND t$(t)="1" THEN LET t(t)=6
7490 RETURN
7500 FOR x=j+j TO LEN x$: IF x$(x)="+" OR x$(x)="-" THEN GO TO 7550: REM calculate offset
7510 NEXT x
7520 LET w=NOT j: RETURN
7550 LET z$=x$( TO x-j): LET x$=x$(x TO ): GO SUB 8900: LET x$=z$
7560 LET w=x
7570 RETURN
7600 REM find symbol
7610 LET v=j: REM set as found
7620 FOR s=2 TO CODE s$(j)+j: IF L$=s$(s, TO 6) THEN LET a=FN v(s$(s)): RETURN
7630 NEXT s: LET v=0: REM not found
7640 RETURN
7700 IF NOT auto THEN GO TO 9000
7710 LET end=0: IF FN i(auto-1)=10730 THEN LET end=1: RETURN
7720 LET a$=""
7730 IF PEEK auto=13 THEN GO TO 7760
7735 IF PEEK auto=33 THEN LET auto=auto+1: GO TO 7770
7740 LET a$=a$+CHR$ PEEK auto
7750 LET auto=auto+1: GO TO 7730
7760 LET auto=auto+6
7770 IF NOT LEN a$ THEN GO TO 7710
7780 GO TO 9020
7800 REM Auto start
7810 PRINT AT 10,10;"Searching..."
7820 LET x=FN i(23635): LET y=FN i(23627)
7830 IF x>=y THEN LET auto=0: RETURN
7840 IF PEEK (x+4)=234 THEN GO TO 7860
7850 LET x=x+4+FN i(x+2): GO TO 7830
7860 IF PEEK (x+5)<>40 THEN GO TO 7850
7870 LET auto=x+6
7880 RETURN
7900 REM This allows reruns
7910 RETURN
8300 REM find op (1)
8310 RESTORE i: LET x=0
8320 READ x$: IF x$="99" THEN LET x=0: RETURN : REM scan tables
8330 LET x=x+j: IF m$=x$ THEN RETURN : REM return if found
8340 FOR y=j TO b: READ x$: NEXT y: REM skip to next item
8350 GO TO 8320
8400 REM find op (2)
8410 READ x$,c$,y$: LET z=VAL y$: IF x$="99" THEN GO TO 8450: REM scan tables
8420 IF x$=n$ THEN LET x=VAL c$: IF x THEN LET b=z: RETURN : REM return if found
8430 FOR y=j TO z: READ x$: NEXT y: REM skip to next item
8440 GO TO 8410
8450 LET x=0: IF NOT z THEN RETURN
8460 RESTORE z: GO TO 8410
8500 REM convert type determine address
8505 LET a=0
8510 GO SUB 8900: IF v THEN LET a=x: LET ec=VAL "6*(x>65535 OR x<-32768)": RETURN : REM check if decimal
8520 IF FN n(x$(j)) AND x$(LEN x$)="H" THEN FOR x=j TO LEN x$-j: LET a=VAL "a*16+CODE x$(x)-48-7*(x$(x)>""9"")": NEXT x: RETURN : REM check if hex
8530 LET L$=x$: GO SUB 7600: IF v THEN RETURN : REM scan tables
8560 LET ec=VAL "6*(FN a(x$(1))=0)": IF ec THEN RETURN
8570 LET s$(ns+2)=x$: LET vdef=NOT j: REM flag unresolved
8580 RETURN
8900 REM vet numeric
8910 LET z=j+VAL "((x$(1)=""+"") OR (x$(1)=""-"")) AND LEN x$>1"
8920 FOR n=z TO LEN x$: IF FN n(x$(n)) THEN NEXT n
8930 LET v=(n>LEN x$): IF v THEN LET x=VAL x$( TO n-j)
8940 RETURN
9000 REM kybrd
9010 INPUT (m$+" "); LINE a$: LET end=NOT LEN a$
9020 FOR x=j 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: REM 4 spaces
9120 LET h$=" ": REM 2 spaces
9130 LET h1=h: FOR x=LEN h$ TO j STEP -j: 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 15,"B","C","D","E","H","L","M","A","BC","DE","HL","SP","AF","IX","IY"
9901 DATA 15,"NZ","Z","NC","C","PO","PE","P","M","","","HL","","","IX","IY"
9920 DATA "(c-INT (c/8)*8)+INT (c/64)=0","1","1","ds+FN L(a-add-2)"
9921 DATA "c=ed OR c=221 OR c=253","2","2","FN L(a+di)","FN h(a+di)"
9922 DATA "1","2","1","FN L(a+di)","FN h(a+di)"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
