ACSEMBLER is a Z80 assembler that loads machine code routines into high memory and then assembles Z80 mnemonics written in REM statements within a BASIC program. Assembly source is delimited by “REM GO” and “REM FINISH” markers, with an “ORG XXXXX” directive specifying the target address in decimal. Labels are supported using a Q-prefix notation (e.g., Q23:), and multiple instructions per line are allowed when separated by colons. The assembler displays addresses, hex codes, and mnemonics on screen during assembly, triggered by RAND USR 30512, and supports a screen-copy pause by pressing “P”. Error codes B, G, H, I, L, N, O, P, and R cover conditions from illegal instructions to out-of-range relative jumps.
Program Analysis
Program Structure
The program consists of two distinct parts. Line 10 is a single enormous REM statement that contains the entire machine code payload encoded as BASIC tokens — a well-known technique for embedding binary data in a ZX81/TS1000 program without needing a separate loader. Lines 20–390 form the BASIC loader and documentation display, which copies the machine code into high memory, then prints extensive usage instructions to the screen before handing control to the assembled routines.
Machine Code Loading
Line 20 saves the program (with the embedded machine code in the REM), and line 30 executes RAND USR 21000 to jump into the machine code contained within the REM statement. This self-relocating stub presumably copies the assembler engine to a fixed high-memory address (around 30512, as referenced in the usage text at line 200). After loading, the user is instructed to issue NEW to clear the low-memory BASIC copy, leaving only the high-memory machine code intact — a classic technique for freeing BASIC RAM while preserving a resident routine.
Assembler Entry Point
Once the machine code is resident in high memory, assembly is triggered by RAND USR 30512 from within the user’s own BASIC program. The assembler scans the BASIC program’s REM statements for the source code, locating the region between a REM GO marker and a REM FINISH marker.
Supported Z80 Features
The assembler supports a substantial subset of Z80 mnemonics. The keyword table embedded in the REM data includes the following mnemonics:
- Data transfer:
LD,LDD,LDIN,LDI - Arithmetic/logic:
ADD,ADC,AND,CP,DAA,DEC,INC,NEG,OR,SBC,SUB,XOR - Bit manipulation:
BIT,RES,RL,RLA,RLC,RLD,RR,RRA,RRC,RRD,SET,SLA,SRA,SRL - Control flow:
CALL,DJNZ,JP,JR,RET,RST,HALT - I/O:
IN,IND,INDR,INI,INIR,OUT,OTDR,OTIR - Stack:
POP,PUSH - Miscellaneous:
CCF,NOP,SCF,CPD,CPI,EX,EXX,IM - Pseudo-op:
DFB(define byte),ORG
Register tokens visible in the REM data include BC, DE, HL, SP, IX, IY, and the individual registers B, C, D, E, H, L, A. Condition codes NZ, Z, NC, C, PO, PE, P, M are also present, with a note in the documentation that Z, C, P, and M must always be followed by a comma.
Label System
Labels use a Q-prefix scheme: a label is defined as Q or Q. followed by a number from 1 to 255 and a colon (e.g., Q23:). They are referenced in instructions such as JR C,Q23. Error code L is reported when a referenced label cannot be resolved.
Numeric Input and Relative Jumps
All numbers must be entered in decimal — the documentation explicitly notes that RST 56 should be used rather than RST 38H. Relative jump offsets must be explicitly signed (e.g., JR Z,+4 or JR -7). Error code R is issued when a relative jump target falls outside the valid −128 to +127 byte range, and error code B covers other out-of-range numeric values.
Display and Interaction
During assembly, addresses, hex codes, and mnemonics are printed to the screen. When the screen fills, pressing P triggers a COPY (hardcopy to printer), while any other key resumes assembly. The BASIC documentation section uses SCROLL loops (lines 140 and 260) and FOR/NEXT delay loops (lines 100–110 and 220–230) to page through the instruction text.
Error Codes
| Code | Meaning |
|---|---|
B | Number out of range |
G | REM GO not present |
H | REM FINISH not present |
I | Illegal instruction |
L | Label not found |
N | Illegal number |
O | ORG not present |
P | REM GO found prematurely, or GO/ORG faulty |
R | Relative jump out of range |
Notable Techniques
- The entire machine code assembler engine is stored inside a single
REMstatement on line10, exploiting the fact that REM data is stored verbatim in the BASIC program area and is accessible to machine code via known offsets. RAND USR 21000on line30bootstraps execution into the REM payload, which self-installs to high memory — a two-stage loading pattern that avoids the need for a separate binary file.- After installation,
NEWreclaims the BASIC program area while the assembler remains resident in high memory aboveRAMTOP, a standard technique for writing resident extensions. - The instruction separator design (colon for multiple instructions per line) deliberately mirrors the BASIC colon separator, which may simplify parsing within the machine code scanner.
Content
Source Code
10 REM PRINT ACS ZACS ZACS ZACS ZLN /#LEN 0NOT Y(LN /# LOAD ▖OLN 0# LET [)]LEN 0NOT TAN LN ;+TAN LN [B]:TAN LN [V]▝TAN LN [X]▛TAN LN E\~~TAN LN C?TAN ▞ ) LIST **LN ##)/ UNPLOT LN ##)[0] COPYLN ##) PLOT COPYLN ###LEN 0/.:.£;S UNPLOT #J##J#<;# RETURN1K▞#[R]#COS /▝▞ COPY6 INPUT #E PAUSE ##76 PAUSE #E INPUT #TAN PRINT VAL FAST#CHR$ AS▀INT -H#CHR$ 0S SAVE LN D# LN ## GOSUB # SAVE ##M5RND2▘ GOSUB ##RNDLN ## LN /# LOAD ▖OLN 0#VAL LPRINT GOSUB # SAVE #;6 SAVE # LPRINT U5RNDX4▖ LPRINT AT LET TAN M5RND FAST GOSUB ##RNDLN 0+Y\~~LN /# LOAD ▖OLN 0# LPRINT GOSUB ##RND/[X]7LN ##FY-[Y]C\,,Y+[Y]C▝INT /HTAN GOSUB # SAVE #Y [<]M SAVE #TAN PRINT VAL 7 FASTLN ##)$#U£##U SAVE ##,[T]4:<,M SAVE #<,M RAND # LPRINT AT LET TAN #### LPRINT AT LET TAN 77 FASTLN ##)$#U£##U SAVE ##,[T]4▒ LPRINT #CHR$ 0**7/ RAND <<<#CHR$ ▘#K SCROLL###/ RAND ADCADDANDBITCALCCFCP DAADECIN INCJP JR LD LDDLDINEGNOPOR OUTPOPPUSRESRETRL RLARLCRLDRR RRARRCRRDRSTSBCSCFSETSLASRASRLSUBXORHALCPDCPIDJNIM INDINIOTDOTI BCDEHLSPIXIY BCDEHL(A NZZ,NCC,POPEP,M, : £)##, RETURN COS [Y]C▞<<<£/ NEXT 7<,[Y]C▞<<£F/ PAUSE 7<,[Y]COS FF<£/ NEXT ) RUN #/▀):#:▘, RETURN COS [Y]C▀</▞7<,[Y]COS F<£/ GOTO : )▌#, RETURN COS [Y]COS <£/ PLOT FASTLN /#Y▒LN /# LOAD ▖O/\,, FASTLN /#Y(/ LOAD LN 0# LPRINT TAN TAN TAN LN 3## RETURN▘TAB :#▞[▒]VAL 77# RETURNA4#77LN ### RETURN▒C\,, RETURN▞C=AT █:▘TAN LN ##AT #LEN ##U SAVE ##:▝TAN 7YH[Y]4▛AT #LEN ▞:▘TAN 7YX[Y]4▖-<>/▝- CLEARAT #LEN ▞#STR$ 7LN CONT #SGN :▀TAN 777LN ###LN ▐##AT # RETURN[▒]C▖YM/▝YU▙#- GOSUB :▝TAN RETURN▝TAB [,]#▞█77# RETURNA4RND77LN ### RETURN▒C▒ RETURN▞C(█:▘TAN LN ##-LEN U SAVE ##:▝TAN 7YH[Y]4▌Y▚:▘TAN 7YX[Y]4▌)▚<>/▀)▚ CLEARSTR$ 7LN CONT #SGN :▀TAN LN ### RETURN▀774: LN ###LN ▐#Y RAND ▟:▘TAN RETURN▌4▖-<>/▝- CLEARSTR$ LN ### RETURN▌4▝CHR$ ▝ RETURN▞4▝CHR$ ▀LN ▐#Y RAND ▟SGN #:▝TAN RETURN▀TAB INPUT #▞[4]: NEW7VAL 7#CHR$ AS" LN ###AT █:▘TAN # RETURN(C£LN ##AT #U SAVE ##:▝TAN 7YH[Y]4▛AT #LEN ▞:▘TAN AT #LEN ▞#7YX[Y]4▖-<>/▝- CLEARSTR$ 7LN CONT #SGN :▀TAN RETURN▖TAB ##YS PRINT 77:▘▞▒Y0[Y]C▖W£( RAND #CHR$ \~~S▀INT )H#LN ## LET ▟77 PRINT LN ### RETURN▞C▒SGN ▙#-ACS :▝TAN 7YH[Y]4▌-▞ LET / INPUT 7YX[Y]4▌)ACS <>/▀)ACS CLEARSTR$ 7LN CONT #SGN LET :▞▟M RAND #:▖TAN RETURN▌TAB [6]#-LN Y[W] PRINT STR$ 777LN ### RETURN\,,40# RETURNQ4▌LN ▞#/▀LN ##SGN LET U SAVE ##U RAND #M SAVE #:▀TAN PRINT # RETURN,C▘77 LET LN ##SGN LET ▟#STR$ # RETURNQ4▌LN ▞#/▀LN ##SGN /ABS RETURN▞4▌YZ:▘TAN RETURN▛4▛▞[S]: RETURN#[8]# RETURN▒4▌YB:▘TAN RETURN\,,TAB H#- CLS2▌STR$ 77# RETURN(CQLN ### RETURN▛C5CHR$ ▌K\~~#LN ▐#SGN #▟:▘TAN # RETURNXSGN 4▖-<>/▝- CLEAR#CHR$ USR #:▝TAN LN ###LN ##SGN #▟:▘TAN 7# RETURNH4▛SGN #CHR$ SQR :▘TAN 7SGN #CHR$ SQR #YX[Y]4▖-<>/▝- CLEARSTR$ 7LN CONT #SGN :▀TAN RETURN\~~4B7777YC[Y]4<FFFLN ###LN ###LEN RND#- GOSUB :▝TAN LN ##U SAVE ##-<=/ PAUSE RETURN"4▛- NEXT 2▖#COS # RETURN£TAB ATN #7Y([Y]C\,,-#Y[U] PRINT STR$ ###7# RETURNH4▌Y DIM :▘TAN 7YX[Y]4▌) DIM <>/▀) DIM CLEAR:▝TAN LN ▞# FAST GOSUB # SAVE #E IF # FAST[J] GOSUB # LPRINT S= GOSUB #77[J] FAST)█ GOSUB # LPRINT S▝INT ,[+]# LPRINT TAN FOR GOSUB #FF FAST)▟ GOSUB # LPRINT #[~~]### LPRINT TAN RETURN$TAB *#7LN ### RETURN\,,CB# RETURN,C▘77# RETURNQC>LN CONT ##LN ###LEN /#U SAVE ##:▝TAN LN [<]##M SAVE #/ CONT # RETURNQ PRINT ATN [<]# LET C▛LN CONT #U SAVE ##:▝-/TAN ###([Y]ASN STEP #LN ### RETURN▛TAB [L]## RETURNI4▞)# GOSUB :▝TAN RETURNR4▌)# GOSUB / POKE RETURNA4#77# RETURN(C9 RETURNI4▌)# GOSUB / REM RETURNR4▌)# GOSUB / PRINT 7# RETURNB4▌Y\~~:▘TAN RETURND4\,,Y,/ PRINT ###S▌FFF/>LN ##-UU SAVE ##U RAND #M SAVE #:▀TAN LN ##£#LN ##VAL #LEN S PRINT 77#CHR$ AS\,,LN ## LET ▟:▘SGN TAN # RETURN(C?LN ## LET AT #LEN RETURN# LIST ##:▝TAN 7YH[Y]4▛ LET LEN ▞AT :▘TAN 7 LET AT LEN ▞#YX[Y]4▖-<>/▝- CLEARSTR$ 7LN CONT #SGN :▀TAN 7# RETURNB4▌Y▝:▘TAN RETURND4▖Y>/ PRINT RETURNH427777#CHR$ AS\,,LN ##Y#▟:▘TAN LN ##-QU SAVE ##:▝TAN 7# RETURNXC▒ RETURNYC▒F###-<>/▝- CLEARSTR$ 7LN CONT ##LN [>]#4 IF 7#CHR$ AS"LN ##SGN #LEN ##:▀TAN U SAVE # PRINT LN ##U SAVE #M RAND # LET M SAVE #SGN 2Q:▖TAN LN ###LN [>]#4 IF 7# RETURNA4?-MU SAVE ##U RAND #M SAVE #:▀TAN RETURNH4▖-6/ FOR RETURNB4▛2#- GOSUB :▖TAN RETURND4▖2#/ NEXT RETURNS4▖2#/ PLOT LN LEN #4▖-<>/▝- CLEAR26:▖TAN 77# RETURN(C## RETURN▘4▖-▘/: RETURN▝4▖-)/ PLOT RETURN▀4>-5LN ""#U SAVE ##U RAND #M SAVE #:▀TAN RETURN▖48#CHR$ AK▖-L/ STOP# RETURNH4▌Y RAND :▘TAN 7# RETURNX4▖-<>/▝- CLEAR2 RAND :▝TAN RETURN▌4▖-<>/▝- CLEARSTR$ LN ##SGN 25:▖TAN 7LN ### RETURN▘4▞)# GOSUB :▖TAN RETURN▝4▌)# GOSUB / POKE RETURN▖4▌)# GOSUB / PRINT RETURN▌4▌)E<>/ PRINT RETURN▞4▌)E CLEAR/ PRINT -EU SAVE ##U RAND #M SAVE #:▀TAN RETURN:4▛ 7Y(#.# RETURN?4:)[C] GOSUB 7# RETURNR4▝2[S]:▝TAN RETURN(4$)[4] GOSUB 7# RETURNR4▝2[K]/ GOTO RETURN)4▌)# GOSUB / PRINT RETURN>4▌Y :▘TAN RETURN<4▒▞[K]: PLOT #[8]# RETURN=4X7# RETURN C? RETURND4▖2[F]/▝2[7]- GOSUB :▝TAN F777# RETURNC4=777LN ##£#LN ###LEN T- GOSUB #:▝TAN LN ##-PEEK U SAVE ##/ PAUSE RETURN+4V▞AT 77# RETURNBC▛#LEN (## RETURNDC\,,#LEN (## RETURNH4>/,7## RETURNX4▖-<>/▝- CLEAR:▝TAN # RETURNA4 FOR #LEN (/▘#:▘TAN RETURN-4▌▞VAL #ACS # RETURN*4▞Y# PRINT # PLOT # RETURN/4F7# RETURNI4▞)# GOSUB :▝TAN RETURNN4▌)# GOSUB / POKE RETURN C▌YTAN :▘TAN 7LN ###LN ###LEN [S]/ LIST RETURN;4Z▞(VAL -ACS 7# RETURN(C\~~LN INT ##AT █#:▝TAN 7# RETURNH4▞AT #LEN ▞/ LIST 7# RETURNX4▖-<>/▝- CLEAR2ACS STR$ 7LN CONT #SGN AT #LEN ▞M RAND #:▖TAN RETURN,4▌Y*:▘TAN RETURN.4?7# RETURNA4▖Y▛/ LOAD ▞ ### RETURN04▞)# GOSUB :▝TAN RETURN14▌▞/### RETURN24▌Y3:▘TAN RETURN34?7# RETURNA4▖Y?/ LOAD ▞▒### RETURN44▌)# GOSUB /INT RETURN54£7LN STR$ #U SAVE #LEN SIN :▘TAN RETURN64▌▞[/]#[3]# RETURN74▖YR/ GOTO RETURN84▞Y[S] PRINT # PLOT # RETURN94▞▞47### RETURNA4▖▞C/ POKE RETURNB4▖▞S/ PLOT RETURNC4▒▞[(]:CHR$ #[7]# RETURND4▞▞[C]: INPUT / PAUSE RETURNE4▌Y#:▘TAN RETURNF4<2[D]- GOSUB 7# RETURNRC▀:▝TAN #LEN (#/ RUN RETURNG4▖2[5]/ SCROLL RETURNH4▒777LN AND #TAN # RETURNI4;7# RETURN04▖2#/▞ RETURN14▖2#/▝2#- GOSUB :▝TAN RETURNJ4▌2[E]### RETURNK4▖2[6]/ PRINT RETURNL4▛2[V]- GOSUB :▝TAN RETURNM4▖2[N]/ NEXT # RETURNC4▌YJ:▘TAN RETURND4▖Y NEXT / PRINT RETURNEC▀INT )G7# RETURNI4▖Y CLS/ SLOW7# RETURNX4▖Y OR / POKE 7# RETURNA4▖Y▒/ POKE RETURND4▖Y FOR / PLOT 77777# RETURNH4▖Y STOP/ LIST 7# RETURNX4▖-<>/▝- CLEAR2 STOP:▝TAN [J]5£#▞ COPY#7( UNPLOT LN G#▘#RNDE£RND GOSUB PI FASTAT 5#RNDY REM GOSUB [L]4▒ # RETURNG4 POKE /▝INT ?7777777# RETURN REM C▝INT /7# RETURNOC▀INT *O7777 FASTLN ##LN [O]#6 IF # LPRINT LN Q# 76 LIST #6 POKE #Y▝LN SAVE #E:RND6 PAUSE #E POKE ##[,]#4<LN N#7# RETURN#4▛777777 6 POKE #LN [=]#$4▀#[,,]#£STR$ STR$ NSGN N GOSUB # PLOT #E IF ##[(]#E PAUSE #76:RNDINKEY$ E IF #) PLOT #,#LN [/]#6 IF #( PLOT E PAUSE #)$ ;6:RNDE POKE #LN STEP #E POKE ##VAL NOT AT 7( RAND E PAUSE #LN RUN # 6 PAUSE #6:RND GOSUB #£RND< FOR ▘[=]▝\,, GOSUB #K)LN 4## RETURN COPYC SAVE #""#LN E\~~6 PAUSE #E POKE ## RETURN:C▛ RETURN#C▛7/ POKE 7# RETURN#C▞6 POKE ##[,]#77777# RETURN REM C▀INT ,W7# RETURNF4 SCROLLU RETURN#XCOS LN [B]#6 POKE #/ LET > ) FTAN SGN GOSUB ### FAST GOSUB ##RNDLN 0+ LPRINT #CHR$ 0F FAST GOSUB ###STR$ TAN M PLOT #£#COS #VAL LN K#AT #EXP # FASTSTR$ VAL LN SAVE #Y NOT AT SGN LPRINT 7<TAN E GOTO #6 IF #E LIST #M RETURN#TAN E SAVE #6 GOTO #TAN 7#CHR$ ATAN STR$ LN ##SGN TAN 7# RETURNXTAN 7# LIST #STR$ LN ##SGN TAN 7LN ##TAN LN ▘#-(TAN ▞ # RETURN:C▒ RETURN#C▖▖7/ NEXT #CHR$ :K▘TAN ▞:TAN M RETURN#▘#RNDE£RND GOSUB PI FASTAT 5#RNDY REM GOSUB [L]4▞# RETURNF4 PRINT TAN INT (LN N#U£#WM£#TAN ▞ # RETURN#COS CHR$ 0**▖7/ PRINT # RETURN:COS RETURN#74 RUN 7777TAN 7# RETURNB4▌Y\~~:▘TAN RETURND4▖Y,/ PRINT FLN [V]####U SAVE #><U IF #><U CLS#> LPRINT #<>#**7/ RAND <<<#CHR$ ▘K\~~# CONT #6 SAVE # LPRINT AT LET TAN ##;#S▝INT ,7# LPRINT TAN RETURN.COS RETURN,COS 7TAN # RETURNQASN [6]#7# RETURNFC▖F#[P]#777LN ##U SAVE # GOSUB # IF #>< GOSUB # IF ##I# FASTAT LN 8## RETURNP4£LN 4?LN #▒LN G##1#LN C##C# #CHR$ 0S▀7/ SAVE #;#U RETURN# RETURN▘4▝INT =E IF ##### RETURN#C▀7/ SAVE 7TAN #K# LLIST # GOSUB # RETURN#E▝RND GOSUB # RETURN#[B] GOSUB ###▀▀▀▀ FOR 5 POKE # GOSUB # RAND FOR E RETURN# GOSUB [K]5 POKE #6▝RND5 SAVE #6▖RND▘#:5▙RND) SAVE # GOSUB [K]UQ RETURN[▒]4$Y4MUSR #M##Y1M;#▘ABS )- 5▙RND#7"#[L]4 RAND Y▞▞\,,5▙RND#7( UNPLOT UQ RETURN[▒]4\~~Y7MACS #YFMH#5[5]+6#RNDTAN
20 SAVE "ACSEMBLE[R]"
30 RAND USR 21000
40 PRINT "-------THIS IS ACSEMBLER--------"
50 PRINT "ACSEMBLER HAS NOW LOADED ITS M/CROUTINES INTO HIGH MEMORY. TO USE THE ASSEMBLER, CLEAR THE LOWMEMORY COPY WITH ""NEW"". THE Z80 MNEMONICS TO BE ASSEMBLED SHOULDBE WRITTEN IN REM STATEMENTS.THESTART SHOULD BE MARKED WITH ""REM GO"" AND THE END MARKED WITH""REM FINISH""."
60 PRINT "THE FIRST INSTRUCTION SHOULD BE ""ORG XXXXX"", WHERE XXXXX IS THE ADDRESS AT WHICH THE ASSEMBLED CODE SHOULD START."
70 PRINT "STANDARD Z80 MNEMONICS ARE USED WITH "","" OR ""."" AS SEPARATORS"
80 PRINT "EXCEPT FOR THE CONDITIONALS ""Z"" ""C"",""P"" AND ""M"" WHICH MUST BE FOLLOWED BY A COMMA EVEN AFTER ""RET""."
90 PRINT AT 21,0;"ACSEMBLER TEXT CONTINUES..."
100 FOR I=0 TO 2000
110 NEXT I
120 PRINT AT 21,0;" "
130 FOR I=1 TO 20
140 SCROLL
150 NEXT I
160 PRINT AT 0,0;"MULTIPLE INSTRUCTIONS PER LINE ARE ALLOWED PROVIDED THAT THEY ARE SEPARATED BY COLONS. LABELS ARE DENOTED BY Q, OR Q. FOLLOWEDBY A NUMBER (1 TO 255) FOLLOWED BY A COLON. THEY CAN BE REFERREDTO BY E.G. ""JR C,Q23""."
170 PRINT "RELATIVE JUMPS MUST BE SIGNED E.G. ""JR Z,+4"" OR ""JR -7""."
180 PRINT "NUMBERS ARE ALWAYS ENTERED AS DECIMAL, SO USE E.G. ""RST 56"" RATHER THAN ""RST 38H""."
190 PRINT "BYTES CAN BE SET TO THE DEFINED VALUE X WITH ""DFB X""."
200 PRINT "ASSEMBLY IS STARTED WITH THE INSTRUCTION ""RAND USR 30512"". THE ADDRESSES, HEX CODES AND THEIR MNEMONICS WILL APPEAR ON SCREEN. WHEN THE SCREEN IS FULL,PRESS ""P"" TO COPY, ANY OTHER KEYTO CONTINUE ASSEMBLY."
210 PRINT AT 21,0;"ACSEMBLER TEXT CONTINUES..."
220 FOR I=0 TO 2000
230 NEXT I
240 PRINT AT 21,0;" "
250 FOR I=0 TO 20
260 SCROLL
270 NEXT I
280 PRINT AT 0,0;"THE FOLLOWING ERROR MESSAGES AREPOSSIBLE:"
290 PRINT
300 PRINT " B - NUMBER OUT OF RANGE"
310 PRINT " G - ""REM GO"" NOT PRESENT"
320 PRINT " H - ""REM FINISH"" NOT PRESENT"
330 PRINT " I - ILLEGAL INSTRUCTION"
335 PRINT " L - LABEL NOT FOUND"
340 PRINT " N - ILLEGAL NUMBER"
350 PRINT " O - ""ORG"" NOT PRESENT"
360 PRINT " P - 1)""REM GO"" HAS BEEN FOUND PREMATURELY 2)""GO"" OR ""ORG"" FAULTY"
370 PRINT " R - RELATIVE JUMP OUT OF RANGE"
380 PRINT AT 17,0;"ACSEMBLER TEXT ENDS."
390 PRINT AT 21,0;"COPYRIGHT (C) ACS SOFTWARE 1982."
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.





