A rather nice assembler utility, adapted from the ZX Spectrum Assembler in Phipps Associates’ Machine Code Tools.
Appears on
Capital Area Timex Sinclair User Group’s Library Tape.
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)"