ZXAS is a Z80 assembler written in machine code, embedded as a REM statement in line 10, with a BASIC loader that invokes it via RAND USR 16514. The program assembles Z80 mnemonics — including ADC, ADD, AND, BIT, CALL, DEC, INC, JP, JR, LD, OR, OUT, POP, PUSH, RES, RET, RL, RLC, RR, RRC, RST, SBC, SET, SLA, SRA, SRL, SUB, and XOR — along with register names such as BC, DE, HL, SP, IX, and IY. The error-reporting routine at lines 9050 reads an error code from address 32651 via PEEK and displays it on screen. A separate input routine at lines 9010–9040 accepts an address value, stores it in two bytes at 32640–32641 using standard high/low byte decomposition, and then invokes a second machine code entry point at address 28565.
Program Analysis
Program Structure
The program consists of just three functional BASIC lines plus a small utility block:
Line 10— AREMstatement that contains the entire machine code assembler binary. The tokenized BASIC keywords and graphic characters visible in the listing are artifacts of the raw binary being interpreted as BASIC text.Line 20—RAND USR 16514launches the assembler by jumping into the machine code stored in theREMbody. Address 16514 is two bytes past the start of line 10’s data (past the line number and length bytes), pointing directly at the first opcode.Line 30—STOPacts as a guard in case execution falls through.Lines 9000–9060— A utility block for configuring the assembler’s output address: accepts a target address viaINPUT, POKEs the high byte to 32641 and the low byte to 32640, then calls a second entry point at address 28565 viaRAND USR 28565, and finally reports any error code read from address 32651 withPEEK.
Machine Code Embedding in REM
Storing machine code inside a REM statement is a standard technique: the BASIC interpreter skips the content entirely, but the bytes are present in memory at a known, fixed address. Since the program is the first (and only) line loaded, line 10 begins at the canonical system address 16509, and the REM data starts at 16514, making RAND USR 16514 a precise and reliable entry point without requiring any address arithmetic at runtime.
Address Passing Convention
The utility block at lines 9010–9040 accepts a 16-bit target address in variable ZZZ and decomposes it into high and low bytes:
POKE 32641, INT (ZZZ/256)— stores the high bytePOKE 32640, ZZZ - 256*INT (ZZZ/256)— stores the low byte (equivalent toZZZ MOD 256, but MOD is not available in this BASIC dialect)
Addresses 32640–32641 fall in the upper RAM area and serve as a parameter block that the machine code routine reads before beginning assembly.
Supported Z80 Instruction Set
The mnemonic strings embedded in the REM data (visible as readable ASCII amid the binary noise) confirm support for a comprehensive Z80 instruction set. Identified mnemonics include:
- Arithmetic/logical:
ADD,ADC,SUB,SBC,AND,OR,XOR,CP,INC,DEC - Bit manipulation:
BIT,SET,RES,RL,RLC,RR,RRC,SLA,SRA,SRL,RLA,RLCA,RRA,RRCA,RLD,RRD - Load/transfer:
LD,LDR,LDD,LDIR,LDDR - Jump/call:
JP,JR,CALL,RET,RST,DJNZ - Stack:
PUSH,POP - Miscellaneous:
OUT,IN,EX,EXX,NOP,HALT,DI,EI,CCF,SCF,DAA,CPL,NEG,RETN,RETI,IM - Registers:
BC,DE,HL,SP,IX,IY, and individual 8-bit registersB,C,D,E,H,L,A
Error Reporting
After assembly completes, line 9050 reads a result code from the fixed address 32651 using PEEK and prints it as ERROR n. This single-byte error code is written by the machine code routine itself, providing a minimal but functional diagnostic channel back to BASIC.
FAST/SLOW Mode Usage
Line 9000 issues FAST before the assembly run to disable the display interrupt and maximize execution speed, while line 9060 restores SLOW mode afterward. This is conventional practice when invoking computationally intensive machine code from BASIC, preventing display refresh overhead during the assembly pass.
Notable Techniques
- The entire assembler — parser, code generator, and output routine — is self-contained within the
REMdata, requiring no additional files or memory setup beyond the two-byte address parameter block. - Using
RAND USRrather thanGOTO USRavoids disturbing the BASIC random-number seed register in a way that could cause issues, and is the idiomatic way to call machine code with no return value needed in BASIC. - The high/low byte decomposition at lines 9020–9030 uses repeated
INT (ZZZ/256)rather than bit-shifting, since this BASIC dialect lacks bitwise shift operators.
Content
Image Gallery
Source Code
10 REM 5[=]RND▘█)) # GOSUB [K]5 #6▖RNDTAN )[:]# RETURN£4▛:Z# RETURNF/# RETURN$4?:#£# RETURNLTAB [7]#7# RETURNT/R RETURN?4▛: # RETURNP/G RETURN▞:*C▞ RETURN▛4::3# RETURNAC. RETURNDC6#[7]# RETURN(4▛#:R RETURNF/,, RETURN)4-#:B RETURNATAB [7]# FOR Q▘G####Y▚[)]#/A RETURN▀4-#:# RETURN0C/:# RETURN1C>:# RETURN2C£#[7]# RETURN:4<# RETURNG:#TAB [7]# FOR Q▝GQ GOSUB G#### RETURN▒4=#:[V] RETURNDC▛:[N] RETURNITAB [7]#7# RETURNR/ AND RETURN▝TAB ### RETURNX4"5[:]#Q▘GQ OR ###F7#[R]C CLS RETURN AND 4▝Q(# RETURN(4#7LN ### RETURN▖TAB [7]#7# RETURN OR 4▝Q)# RETURN)TAB [7]#7# RETURN.TAB [7]#7LN ##5[:]#Q▘# RETURN▀4▞GQ STOP###OGQ<> RETURN▌C PAUSE Q CLEAR RETURN▞C GOTO #[7]# RETURNA4B7# RETURNFTAB [7]#7# RETURN.TAB [7]#7# RETURNATAB [7]#7# RETURNFTAB [7]#5[:]#Q▘GQ▒###LN ### RETURN▝TAB [7]#7Y.[Y]TAB [7]#7LN ##Y▀[S]TAB [7]#5[:]#Q▘GQ FOR #### RETURNNTAB [7]#7# RETURNZTAB [7]#▘( ###[J]M["]####77# RETURN REM TAN 5 COPY COPY6ORND#D▝ OR STR$ FASTVAL LN #AT LPRINT SGN OR TAN :ACS GOSUB #[?]# RETURN<C▀ RETURN+""7#F RETURNA""5[:]#Q▘Y▛█7# LPRINT ###6[=]#5C#8 FASTE[=]#TAN )X#=STR$ TAN )3#=TAN LN B#[J]5 #)▘#▘ COPY▘# GOSUB [K]M[~~]#M["]#▞#▖5#RND777LN ▚#C-7#[S]4 CLS[R]) # GOSUB #S▞Y▘M["]#TAN ;/ LLIST F#F# GOSUB #▚#777#[R]C CLS RETURN(4 OR 6[▒]#5[~~]#OE[▒]#6▜#E█#6▙#E▜#7#[R]C CLS▞#▖[S]4=7#7# GOSUB #▚#7LN ▚#C SCROLLY▝M["]#TAN RETURN)4▒U[~~]# RETURN▝#-# RETURN*4▛[S]C OR 7#/ RAND RETURN:TAB )#7# RETURNL4*▞ 7#▖CHR$ 0ACS #4>#CHR$ AACS #C"# RETURN▖4 FOR Y▀M["]#TAN ▌C RUN 6▜# ▌F#CHR$ 0##[R]CA▌F#CHR$ 0▗#ACS 6ACS 6▙▟##[R]C=F#CHR$ 0#▗▙▗▗▗▙[R]▗▗SSIN ▟#[J] 5 #ACS 5EXP #,, GOSUB #▙##7#E▜#F7#[R]C CLSCHR$ AACS #C▞Y▖M["]#TAN #CHR$ YACS #C NEXT # IF #E£RND76[£]#FY#W:/▞47Q ( CLS7#$4 POKE TAN Y COPYW[R] GOSUB PIK IF ,,LEN 0><TAN #▞▖ACS Z( UNPLOT LEN 0><# NEW?LEN 0><TAN E▚# GOSUB #[£]#▘ CONT ▀LN ##▘# LN ##:~~LN ##:▘LN ##<E▙#LN ###LN ##< OR 5[?]# OR : OR #7 OR #£U[:]#[)]ACS #C▖<</▀LN ##<Y▖[T]4 FASTE▜#▞#▖# RETURN;C>[S]C?,[S]4▌< GOSUB #[£]##>7</ DIM 6▜#E[£]#)5 ;6[£]#U[:]##▞ 5[?]# GOSUB #▙# GOSUB [K] GOSUB #▙#E£RND▘""▝,, GOSUB #[£]#[R] GOSUB PIK▞LN [£]#LN B#Y#<= RETURNACS #COS E▜## RETURN;ASN #####TAB ##▞ LET PRINT ( UNPLOT #[£]##CHR$ 0 IF L##CHR$ A PAUSE L#7/ LET FAST OR 5 )▘ OR F#CHR$ 0 IF ###CHR$ A PAUSE ###CHR$ . OR #; ( UNPLOT [R] GOSUB # FAST5 ▞~~;( CLEAR FOR LPRINT / OR LPRINT TAN #4▀ OR LPRINT TAN Y▌M["]# LPRINT LPRINT TAN ) #CHR$ G PAUSE [=]##CHR$ 0 IF [=]##▞▖ACS 6S)ACS 7#EXP #( POKE #[N]#7/ TO TAN #COS Y▌M["]#TAN ADCADDANDBITCALCP DECIN INCJP JR LD OR OUTPOPPUSRESRETRL RLCRR RRCRSTSBCSETSLASRASRLSUBXOR 6▜#Y COPYM[<]#: )[1]#,[R]CM[Y]C▞<<<£/ NEXT <7,[Y]C"<<,<£F[Y]4,/ LIST <7,[Y]C:£FFF▞▀7<,[Y]4▞( SAVE #M[<]#LN L#C£▞█ RETURN▘C▞ RETURN*4.▞[/]#M[?]#7#[R]C CLS RETURNATAB [$]#7# RETURN.4INKEY$ Y▘# CLEAR#:RND RETURN▀C£:█ RETURN(C▞ RETURN/4G:""7#[R]C CLS RETURN8K.CHR$ 0S*#[J]LEN ▒( UNPLOT ▟#:ACS GOSUB #[?]#7# RETURN.Y▝ASN CLEAR#Y▖M["]#TAN ▞[4] RETURN▝C/▞[S] RETURN▌C>▞[K] RETURN£C£▞[(] RETURN0C▞ RETURN14"▞[C]:▘ GOSUB #[:]## #▞( RETURN>C9▞ RETURN<C3▞/ RETURN=C;▞▒ RETURN+C<▞4 RETURN;C$▞C RETURN,C▛ RETURN.TAB EXP #▞SLN [5]# Y▝M[:]# RETURN<C▖ RETURN+4*7#F RETURNA4(Y▘M[:]#U[(]#LEN ▛M[?]####7#[R]C CLS RETURN AND 4▝Q(# RETURNA IF ## RETURNM PAUSE ##▞▛ RETURNIC9▞ RETURNBC3▖ RETURNCC,▖ RETURNDC+▖ RETURNEC(▖ RETURNHC"▖ RETURNLC▞Y▖M["]#TAN 5[:]#U[:]##- ;#▚#### RETURN(COU[:]# RETURN▝4▞Y▖M["]#TAN U[?]#LEN #:▝# GOSUB #[:]## RETURN$C?LN 6# OR #[R]4 LPRINT #M[(]####7LN ## FOR / INPUT 7# RETURNH457# RETURNL4SIN 7# RETURN)4▝Q)# RETURN)4[V]5[:]##▞ ,,Y▞▚#### RETURNI4[C]7#7# RETURN+4▝Q+ RETURN-4▝Q-#VAL 7# RETURN$C<LN 6# OR #[R]C▛ LPRINT Y▌M["]#TAN # OR /,,7LN ###[R]4 GOSUB ##AT # RETURN)4▝Q)# RETURN)4## RETURN+4▛ACS #4CHR$ #/" RETURN-4P[J][>]ACS #CSTR$ #5[:]##LEN ▝# RETURN▖C▒G#LEN ▞G#/£GG#LEN ▞GG#I[(]QACS G##:<> RETURNXC£: CLEAR RETURNYC▞Y▖M["]#TAN I[?]####BCDEHLSPIXIY )##▞ ▖,[Y]4,,<7,[Y]COS <F/ PAUSE <<[R]COS / GOTO LN ##U[<]#:#[R]C▞ RETURN▘CL:PI# RETURN▀C▞Y▖M["]#TAN 7# RETURN.4 POKE 7LN ##Y▖[S] IF [7]##LEN (( UNPLOT CHR$ (5[:]#Q▝GQ GOSUB G####7# RETURN.4M7#LN ###[T]4▖-D/># RETURN▌ PAUSE [7]# RETURN▀ASN [7]#Y RAND LEN (( UNPLOT ##2 RETURN▀C>2<> RETURN▌C£2 CLEAR RETURN▞C▞Y▖M["]# OR 5[:]#Q▘#[R]4▀G/▖OG#G####BCDEHL(A # RETURN(4▝Q(LN USR #▞ COPY▖,[Y]COS [R]COS </ RUN RETURN"TAB [H]#E▜#777#[R]C CLS RETURN(4▝Q(LN ### RETURN▛TAB UNPLOT #LN TAB ## RETURN▒4G#▞# RETURNIC£▞# RETURNRC▞Y▖M["]#TAN 7# RETURN.4 POKE 7# RETURNA4 INPUT 5[:]#Q▝GQ GOSUB G#### RETURN▞ASN OR #7# RETURN.4CHR$ 7##▞# RETURNIC TO ▞# RETURNRC OR LN TAB ## RETURN▞ASN [9]# RETURN▒C=5[:]#Q▘GYRND█ACS 5ACS 5ACS 5▟#####M[:]## RETURN$C- RETURN0 AND [7]# RETURNAABS [7]#LN 6# OR #[R]TAB [7]##/=7# RETURN0 AND [7]# RETURNGABS [7]#LN ###[R]TAB [7]#5[:]#ACS AACS AACS AY▞▚Q▝G#G####7LN ###M[?]# RETURN▖4▞Y▖M["]#TAN RETURN▖K:7# RETURN)4▝Q)# RETURN)COS / CONT RETURN▛COS 7# RETURN+4▝Q+ RETURN-4▝Q-# PRINT 7# RETURN$C= RETURN0SG RETURNAKCLN 6# OR #[R]44# OR />7# RETURN0S- RETURNGK>LN ###[R]4"## LET RETURN+C= RETURN-C▛ LPRINT Y▖M["]#TAN # RETURN▟K PRINT GOSUB #/▌ACS #4 GOSUB #M[(]# # RETURN)4▝Q)# RETURN)4>=TAN VAL LN >#AT U["]#[R]""ACS 5ACS 5ACS 5Y#▟#U[?]# RETURN▀4~~5[:]#Q▘G####K=## RETURN#TAB [7]##:~~ RETURN▘C NEW:, RETURN▝C STEP RETURN▛C*5[:]#Q▀G#Q<> RETURN▌C▝Q CLEARG##G##### RETURNLC# RETURN$C< RETURN0 AND [7]# RETURNAABS [7]#LN 6# OR FAST OR SGN /?7# RETURN0 AND [7]# RETURNGABS [7]#LN ##U["]#[R]"" FAST5[:]#Q▀GQUG#G# LPRINT # RETURN)4▝Q)# RETURN)ASN ###[7]#Y▀M[:]#YUM[?]#7# RETURN0 AND [7]# RETURNAABS [7]#LN 6## RETURN)4▝Q)# RETURN)TAB [7]# OR #[R]TAB [7]##[J]ACS 5EXP #5 #,,#7#5[:]##GG RETURN▀C▘G#G##### RETURNL4.7LN 6# OR #[R]TAB [7]#[J]ACS 9EXP #▘ #,,#7#STR$ OR SGN TAN RETURN$C> RETURN0 AND [7]# RETURNAABS [7]#LN 6# OR FAST OR SGN TAN 7# RETURN0 AND [7]# RETURNGABS [7]####LN >#U["]#[R]""U[?]# RETURN▛ASN ▙#7# RETURN.TAB [7]#7LN TAB #U[?]#:<> RETURN▌C▞ RETURN▞4U: CLEAR#M[?]## RETURN▞ASN [7]# RETURN▒C(LEN #5[:]#Q▀GG##G####LN [=]#U["]#[R]""#[R]TAB [7]#5[:]#Q▖#M[>]#YQ/<>:> RETURN▝C▞ RETURN▘4>:▝5[:]#Q▘G## RETURN▛TAB [7]##### RETURN▒C£5[:]#Q▘LEN #G####LN [=]#U["]#[R]""#[R]TAB [7]#5[:]#Q▝GQQG####LN [=]#U["]#[R]""# RETURN)4▝Q)# RETURN)TAB [7]#7# RETURN.TAB [7]#7STR$ LN ##SGN # RETURN▛#5[:]#4£ RETURNATAB [7]#Q▀GQM/W# RETURN▘4▖:#/: RETURN▝4▖:#/▞ RETURN▖4":#Q▖GQ GOSUB G#/0 RETURN▀4▛Q▀GQ6/) RETURN▌4▖:<>/▝: CLEARQ▖G#GQ6G#G####7# RETURN.TAB [7]#7# RETURN(4▝Q(# RETURN(4#7VAL LN [=]#AT # RETURN)4▝Q)# RETURN)TAB [7]#5[:]#Q▖# RETURN▌K0 RETURN▀4"PGQEG#G####YVLEN (( UNPLOT GQ GOSUB G#/ GOTO ▞<> RETURN▌C▝▞ CLEARG#/<># RETURN▖4▌# RETURNAKEVAL LN [=]#AT U["]#[R]""5[:]#Q▀# RETURN▌K▒Y LET LEN (( UNPLOT /ASN OGQ<> RETURN▌C▝Q CLEARY5/[W]LN ##5[:]##Q▝ RETURN▀4▛PGQ RAND ###GQ<> RETURN▌C NEXT Q CLEAR RETURN▞C GOSUB #[7]# RETURN▒C▌ RETURN▞TAB ##7#[R]C CLSLN ### RETURN▛CL5[:]#Q▘ RETURN▌K,#Y LIST LEN (( UNPLOT #U[<]#:▀ RETURN▒C▝:"#▟G####OGQ<> RETURN▌C▝Q CLEAR▞4/ STEP LN TAB ## RETURN▒ASN [7]# RETURN▞C2▖Y SAVE LEN ▒( UNPLOT 5[:]#Q▘G#U[<]#▞▌ RETURN▞C▘▌#█####LN >#U["]#[R]""5[:]#Q▘U[<]#:P RETURN▞C▝:OG# RETURN▀4▖####HQ▀GG##G#I[?]Q<> RETURN▌C▛Q CLEAR RETURN▞TAB [7]#### RETURN:C" RETURN?4#7# RETURNHTAB [7]#7#[R]C CLSLN ### RETURN▖ASN [7]# RETURN▛4)# RETURNATAB [7]#7# RETURNFTAB [7]#: LET /" RETURN▌K.Y[L]LEN (( UNPLOT #5[:]#Q▘U[<]# RETURN?#4▝LEN ▖G####5[:]#Q▝GQ<> RETURN▌C▝Q CLEAR: LPRINT / TO RETURN-4L7#[R]C CLSCHR$ 0 IF [7]# RETURN▖ABS [7]##Y[R]▖LEN (( UNPLOT #7# RETURN0C,, RETURN8TAB [7]##LEN ▒#5[:]#Q▘G#### RETURN,,CPI RETURN▖4,,7# RETURNLTAB [7]#/P RETURN)TAB 6#7#[R]CF5[:]#Q▘ RETURNI4":#OGQ GOSUB G####:# RETURNNC LET RETURN;C▛▞#▖[S]TAB [7]#GQTAN ###7#[R]C CLS RETURNZ4▖▞▝/Y RETURNC4▖▞▖/Q RETURNM4▖▞▒/I RETURNN4<7# RETURNZ4▖▞▘/4 RETURNCTAB [7]#▞▀/* RETURNPC▖▞ /?7#▞▌ RETURNOC▛▖ RETURNEC▝▖F#[R]CMY[S]LEN ▒( UNPLOT #U[<]# RETURN): C▒ RETURN,,:▝C▝:▖#▟M[?]##[R]4▛WM[:]####7# RETURN.TAB [7]#7/#U[<]#▞LN RETURN▖C▝▞##M[?]# RETURNLN CZ# RETURN(4▝Q(# RETURN(4N7LN ##7# RETURN)4▝Q)# RETURN)TAB [7]#5[:]#Q▘# RETURN▀4▞GQ DIM ###OGQ<> RETURN▌C PAUSE Q CLEAR RETURN▞TAB [7]#/ DIM LN [=]#U["]#[R]""5[:]#Q▀GG#G#### RETURN~~TAB STR$ #7#[R]C CLS RETURNN:▒4▀: 7# RETURNC▞KC~~ RETURNZ▞4C▖Y//~~7# RETURN.TAB [7]#7#▟M[?]#Y▝M[:]## RETURNLC2)##STR$ Y COPYM[(]#LN U#U["]#[R]4▖ LET ###U[(]# RETURN COPYCOS / POKE LN [=]#U[~~]# RETURN▘4▛[J]M[(]####E▙# FOR GOSUB #)# ;#[R]C▞Y▞M["]#TAN #CHR$ █/ LPRINT LN TAB #7# RETURN▞ASN [7]# RETURN▒ASN [7]#▖YSLEN ▒( UNPLOT M[(]#TAN 7# RETURNCTAB [7]#7# RETURN)4▝Q)# RETURN)TAB [7]#TAN RETURN$C# RETURN▛TAB ##7#[R]C CLSLN [9]## RETURN.TAB [7]#7# RETURN(4▝Q(# RETURN(C,LN [O]##[R]TAB [7]#U["]#[R]""5[:]#Q▝GQ<=G####LN [Z]#U["]#[R]""5[:]#Q▝GQ GOSUB ###7# RETURNDASN ["]# RETURNIASN ["]#F7#[R]C CLS# RETURN(4▝Q(# RETURN(44LN [Z]#7# RETURN.TAB [7]#7LN [9]#U["]#[R]""5[:]#Q▝GQ GOSUB GO###LN [O]## RETURN.TAB [7]#7# RETURNBTAB [7]#U["]#[R]""#[R]TAB [7]#5[:]#Q▝GQPEEK G####5[:]#Q▝GQ GOSUB GQ[F] RETURNDASN ##Q[7]###CPEXIMINLDRLRROTDIDJEICCHANENOSCDA E▜#)[4]#: £,[R]ASN [7]#0[Y]C▀0/ NEXT 7,[Y]C▖0F/ REM 7# RETURN▘4(# RETURNL4=5[:]#Q▘GQJ### RETURN▖C▌ RETURN▌TAB S#▞ # RETURNIC▛ RETURNDTAB [7]#ACS **7# RETURNR4▝ACS STEP 5[:]#Q▝GQ GOSUB 7Y[4]█## RETURN▌C▞O RETURN▘C▘O###U[<]#▞[▒][R]TAN RETURN,,C▖ RETURN"4)5[:]#Q▘GACS 5ACS 5YINT ▟##### # RND
20 RAND USR 16514
30 STOP
9000 FAST
9010 INPUT ZZZ
9020 POKE 32641,INT (ZZZ/256)
9030 POKE 32640,ZZZ-256*INT (ZZZ/256)
9040 RAND USR 28565
9050 PRINT AT 21,0;"ERROR ";PEEK 32651
9060 SLOW
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.