A rather nice assembler utility, adapted from the ZX Spectrum Assembler in Phipps Associates’ Machine Code Tools.
Content
Image Gallery
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)"