ACS-DEBUG is a Z-80 machine code debugger that loads itself into high memory (addresses 25850–27640) and is invoked via RAND USR 27467. The program provides five facilities: executing machine code from any address, setting breakpoints with full register and flag display, moving blocks of code in memory, listing memory contents in decimal, and searching memory for a string. The machine code payload is embedded in line 20 as a large tokenized REM statement, and line 21 uses RAND USR 18300 to copy or initialize it into high memory during loading. It is designed to work alongside other high-memory tools such as an assembler or program store, provided those are loaded first.
Program Analysis
Program Structure
The program is organized into two distinct phases: a machine code installation phase and a BASIC description/documentation phase.
- Lines 10–21: Setup. Line 10 is an empty
REM. Line 20 is a massiveREMcontaining the entire machine code payload as tokenized binary data embedded in the program listing. Line 21 executesRAND USR 18300, which triggers a machine code routine (presumably already resident or bootstrapped from the REM data) to relocate the debugger into high memory. - Lines 30–110: Print a feature overview to the screen.
- Lines 120–130: A delay loop (
FOR N=1 TO 1000) to pause after the first screen of text. - Lines 140–170: Clear the status line and scroll the screen 19 times to make room for additional text.
- Lines 171–174: Print extended documentation covering memory addresses, usage instructions, and a copyright notice.
- Line 200:
STOP— ends the BASIC portion. - Lines 210–220:
SAVE "ACS-DEBU[G]"followed byRUN, used to re-save and re-execute the loader program.
Machine Code Embedding via REM
Line 20 is the core of the program. The entire Z-80 machine code for the debugger is stored as binary data within a REM statement. This is a standard technique: since REM line content is never parsed by the BASIC interpreter, arbitrary byte values — including machine code opcodes — can be stored there. The BASIC system stores the bytes verbatim after the REM token.
The decoded content of line 20 includes recognizable debugger feature labels such as BREAKPOINT=, LIST FROM=, EXECUTE ADDRESS=, MOVE FROM, MOVE TO, PROGRAM END, STRING=, and FLAGS=, confirming the five advertised facilities are implemented entirely in machine code.
Installation Mechanism
Line 21 calls RAND USR 18300. At address 18300 there is presumably a small machine code routine (possibly bootstrapped from the REM data itself, or already present in ROM/RAM at that address) whose job is to copy the debugger payload from line 20’s REM body into high memory at address 25850. After installation, the debugger is invoked independently via RAND USR 27467 and the low-memory BASIC copy can be deleted with NEW.
Memory Map
| Address | Purpose |
|---|---|
| 18300 | Bootstrap/install routine entry point (called by line 21) |
| 25850 | Start of ACS-DEBUG in high memory |
| 27640 | End of ACS-DEBUG in high memory |
| 27467 | Entry point to invoke ACS-DEBUG after installation |
The debugger occupies 1,791 bytes of high memory (25850–27640), leaving room below for a user program to be written or loaded.
Debugger Features Identified in REM Data
- Breakpoint mode (B): Halts execution, displays CPU flags and all register contents including values at addresses pointed to by 16-bit register pairs.
- Execute (E): Calls a machine code routine from a user-specified address.
- List (L): Dumps memory contents in decimal from a specified start address.
- Move (D/U): Relocates a block of code up or down in memory between specified addresses.
- String search (S): Scans memory for the occurrence of a specified string.
- Command mode (R): Entry point for the interactive command interface.
BASIC Idioms and Techniques
The delay loop at lines 120–130 uses FOR N=1 TO 1000 / NEXT N as a simple timing pause — a common idiom in the absence of a calibrated PAUSE command. The screen-scroll sequence at lines 150–170 uses 19 iterations of SCROLL to clear the display for a second page of text, simulating paged output. AT 21,0 is used in lines 110 and 140 to write and then erase a “press any key to continue” style message on the bottom line without affecting the rest of the display.
Compatibility Notes
The documentation in lines 171–172 explicitly states that ACS-DEBUG is designed to coexist with other high-memory resident tools (such as an assembler), provided those are loaded before ACS-DEBUG. All input and output within the debugger operates entirely in decimal, with no hex support — a deliberate design choice noted in line 173. Rubout (delete) is stated to work only before NEWLINE is pressed; pressing NEWLINE first clears the screen for re-entry.
Anomalies and Notes
- Line 210 saves the file as
ACS-DEBU[G]— the[G]escape represents the letter G in the tokenized listing, making the full filenameACS-DEBUG. - Line 220 (
RUN) afterSAVErestarts the loader automatically after saving, which is a convenience for distribution. - The REM data in line 20 contains numerous BASIC keyword tokens interspersed with binary machine code bytes. This is expected behavior: the BASIC tokenizer stores keywords as single-byte tokens even inside REM lines on this platform, so the decoded listing appears to contain keywords like
GOSUB,RETURN,PRINT,FOR, etc. These are not actual BASIC instructions but opcode bytes that happen to share values with BASIC keyword tokens.
Content
Source Code
10 REM
20 REM ACS-DEBUG##PRESS##R FOR COMMAND MODE / BASIC##B BREAKPOINT##E EXECUTE PROGRAM##L LISTS##D MOVE DOWN##U MOVE UP##S STRING SEARCH#LN [V]▝TAN LN [X]▛TAN LN ;+TAN LN 0+TAN LN [B]:TAN LN C?TAN LN E\~~TAN LN #"TAN FASTVAL LN ### RETURN COPYC SAVE ##LN ###AT LPRINT TAN # NEXT #S# #PI#X# CLS25 6[H]#76[J]#[J]M5RNDLN [,]##Q# LET U5RND# LET ( CLEARLN [>]#Y=NOT />= LET RETURN#C. PRINT CHR$ AS▀ LET /<> LET NOT CHR$ 0 PRINT LN [V]▝# RETURN COPY4 SAVE 55RNDO/ASN U5RND RETURN COS LET LN ▙# GOSUB #[J]#LN ▚# LOAD ▖OLN [~~]#E[H]#\,,6[H]#U5RNDXCOS M5RND GOSUB #[J]#LN ▚#Y\~~LN ▙##[G]##AT LPRINT TAN 5(B6[H]#)▌ GOSUB #[J]# GOSUB #[L]# GOSUB #[L]# GOSUB #[H]##5 ▞(ACS )* GOSUB # GOSUB #K▘;Z( NEXT ACS )*▞ #LEN 0NOT LN ▚# GOSUB #[H]#LN ▚# LOAD ▖OLN [~~]#E[L]#[J] GOSUB PI[J]6[L]# GOSUB #[H]#LN ▚#Y\~~LN ▙# LOAD ▌OLN [~~]# GOSUB #[H]# GOSUB #[J]#[1] GOSUB #[J]#4[5]TAN LPRINT 6[N]#Y NOT AT GOSUB #SQR #LN ##Y NOT GOSUB # RNDLN ##LN <>#E[N]# FASTTAN E[P]#)5 ;6[P]#6:RNDTAN LN [:]#▘ IF #\~~▀ RETURN#C▀NOT / RUN LN [,]# PRINT LN [>]# LET RETURNRCOS RETURNBASN ## RETURNEASN [8]# RETURNDASN ATN # RETURNLASN ## RETURNUASN RAND # RETURNSASN O## FOR #BREAKPOINT= LIST FROM= EXECUTE ADDRESS= MOVE FROM MOVE TO PROGRAM END STRING= ▞ LN [-]#TAN )A#:£LN ##LN EXP #E[H]#6[R]##M##7#MCODE #7#MVAL #Q#FQ SAVE FQ#LN [>]#)X#:)LN ##LN EXP #LN [>]#)X#:▒LN ##Y?NOT LN [,]# RETURNRASN LPRINT # RETURNE4 POKE E[H]##M STEP ##M TO #LN [>]#5 ) [J]#S#E[R]#U###7UCODE ##7UVAL ##LN [>]## FOR # CLEAR FAST<> FAST FASTSTR$ VAL PRINT FASTSTR$ VAL PRINT LN )#E£RND)▖ YA▞▌;#W( CLSYH;#YL;#E£RND)8 ;6[P]#6:RNDAT GOSUB #[H]##▞ LN ##)▀ GOSUB #[J]#AT GOSUB #[H]#LN ###▞ LN ##LN ## GOSUB #[H]#▞ LN ## GOSUB #[J]#1 GOSUB #[J]#4<=/,E[P]#)▖ ;6[P]#6:RNDTAN LN [/]\~~TAN FLAGS= #E£RND)# ;6:RND▘##\~~▀ RETURN#C▀NOT / RUN LET PRINT K▀YCNOT LET PRINT PAUSE [7]#YMNOT LET PRINT LLIST [F]#YVNOT LET 4▀YZNOT E£RND)COS ;6[P]#6:RNDYBNOT WNOT LN [W]#YDNOT WNOT LN [W]#YHNOT YLNOT LN [W]#YINOT YXNOT LN [W]#YINOT YYNOT LN [W]#YSNOT YPNOT Y NOT GOSUB #[H]# GOSUB #[H]# GOSUB #▞#LN ##Y NOT GOSUB # REM #LN ##LN .## LPRINT # GOSUB ## GOSUB ##LN ##TAN LN <>#LN <>#YINOT Y=NOT Y NOT ULN ##▞ LN ##LN <>#YRNOT Y=NOT Y NOT UATN ##▞ LN ##LN [,]#TAN )M#:"LN ##LN EXP #LN [>]#E[H]#6[N]#LN [>]#E£RND76[P]#)= GOSUB #[T]# GOSUB #[N]#LN ##Y=NOT E[N]##▞ #76[N]#LN ## GOSUB #[T]#1 GOSUB #[T]#C▌LN <>#/**LN [,]# RETURNCC""LN [>]## FOR #)##:\~~LN ##LN EXP #LN [>]#E[H]#6[U]#)##:▒LN ##LN EXP #LN [>]#E[H]#TAN LN [A]#6[W]#)##:£LN ##LN EXP #LN [>]#E[H]# GOSUB #[U]# GOSUB #7##▀E[U]# GOSUB #[W]# GOSUB [K]#[7]#LN [A]#6[W]#)##:£LN ##LN EXP #LN [>]#E[H]#6[Y]# GOSUB #[U]# GOSUB #7##▀E[W]# GOSUB #[Y]#; GOSUB #[U]# GOSUB # FOR E[Y]# GOSUB [S]#[7]#/\,, RETURN#TAB NEXT ##M# ▞-Y 5[R]#6[N]##7( UNPLOT LN [>]#E£RND)\,, ;6[P]#)##:▒LN ##E[P]#6:RNDLN EXP #E[N]#U[H]##▙##▙##▙##▙#/\,,TAB LLIST # LET #>=# LN [>]## FOR #LN [>]#E[N]#Y CLEAR#7#/▖▘ 5[R]#▞ # RETURN CLEARC▖7▖/ RUN 7# RETURN CLEARC▀▖/ INPUT #M[.]#)##:\,,#K#LN [>]# GOSUB #[H]#5 COPY# GOSUB #[B]##E[H]#)[R]#, GOSUB [L]F6[H]# GOSUB #[1]# LLIST 6#U[.]##)[R]#,[Y]4▞<7( SAVE /▛E[H]#7#+#E[H]#6[N]###LN ##LN [,]# RETURNS4:LN [>]#### GOSUB #[1]##USR #LN [>]####▘ LN ##LN [,]#LN [>]#/ LOAD /\,, PRINT U5RND RETURN ###LN ##LN EXP ##TAB #E[N]#7#+#UQ RETURN[▒]TAB FOR #5F?6[?]#51+6▄#54+6▗## FOR #6ATN #LN ##TAN RETURN#ASN CLEAR##A # SLOW#Y2 GOSUB #LN [>]#TAN #76[N]#LN <>#LN [,]# RETURN#C RAND RETURNX4▞LN [>]##[:]# RETURNRASN #####LN [>]#E[W]#### LOAD ▖OLN [~~]# GOSUB #[J]##/###### GOSUB #G#E▝RND[B] GOSUB #6▝RNDEG#[B] GOSUB # RAND E▖RND GOSUB #G#[B] GOSUB ### GOSUB #I# GOSUB # REM GOSUB ###E▝RND GOSUB ###[B] GOSUB ###▀▀▀▀ FOR 5 PLOT # GOSUB # RAND FOR E## GOSUB [K]5 PLOT #6▝RND5 IF #6▖RND▘ RETURN▞5[)]RND) IF # GOSUB [K] )7▛5[)]RNDY #7.#[N]4 RUN 5#RNDQ Q 5[$]RNDQ 5##Q ▞£5##Y #7( UNPLOT ▞\,,5▙RNDY▘#7( UNPLOT )PI 5[I]#Y #7.#[N]4 RUN TAN TAN TAN TAN #5EXP #6STR$ #5TAB #6**#5[N]#6<=#5+#6 TO #5 FOR #6 SCROLL#5[?]#6 GOSUB #5▄#6 NEXT #5▗#6 RAND #5 FOR #6 UNPLOT #5ATN #6 COPY#5##6▝#5 CLEAR#6▒#5 SLOW#6:#5[>]#6+#TAN #PI5##6#PI6#PI5<>#6#PI5[N]#6#PI5[P]#6#PI6#PI5[:]#6▙PI5 IF #6▐PI5[,]#6[)]PI5[>]#6[+]PI5##6[2]PI5[8]#6[7]PI5ATN #6[C]PI5##6[H]PI5 RAND #6[M]PI5O#6[R]PI5 FOR #6[U]PI5[-]#6$#5A#6)#5##6-#5EXP #6;#5[H]#60#5[R]#63#5##67#76C#76H#Y#MK#Y SAVE MN#5[>]#6S#5X#6V#5##6RND#5EXP #6##5[>]#6##5X#6##5##6##5[,]#6##5 LPRINT #6##5[H]#6##5 STEP #6##5 TO #6##5[>]#6##5[R]#6##5##6##76█#76▐#5[>]#6[,,]#5 FOR #6[£]#TAN Y? RETURND▘ ▘YC RETURND▘ ▘▝▀ ▘▝▀▘▝▀ ▘▝▀ ▘▝▀ REM # SLOW#
21 RAND USR 18300
30 PRINT "--------THIS IS ACS-DEBUG-------"
40 PRINT
50 PRINT "DESIGNED FOR THOSE STARTING TO WRITE Z-80 MACHINE CODE ROUTINESACS-DEBUG PROVIDES THE FOLLOWINGFACILITIES:"
60 PRINT " 1) EXECUTE A M/C ROUTINE FROM ANY ADDRESS."
70 PRINT " 2) SET A BREAKPOINT ANYWHERE, DISPLAY THE FLAGS AND THE CONTENTS OF THE REGISTERS AND MEMORY LOCATIONS ADDRESSED BY THE 16-BIT REGISTERS."
80 PRINT " 3) MOVE A BLOCK OF CODE UP OR DOWN IN MEMORY."
90 PRINT " 4) LIST MEMORY CONTENTS IN DECIMAL."
100 PRINT " 5) SEARCH MEMORY FOR THE LOCATION OF ANY STRING."
110 PRINT AT 21,0;"ACS-DEBUG TEXT CONTINUES..."
120 FOR N=1 TO 1000
130 NEXT N
140 PRINT AT 21,0;" "
150 FOR N=1 TO 19
160 SCROLL
170 NEXT N
171 PRINT AT 0,0;"ACS-DEBUG OCCUPIES MEMORY FROM 25850 TO 27640 AND CAN BE USED WITH PROGRAMS THAT OCCUPY HIGHERMEMORY, E.G. PROGSTORE OR ACSEMBLER, PROVIDED THAT THESE PROGRAMS ARE LOADED FIRST."
172 PRINT "ACS-DEBUG LOADS INTO HIGH MEMORYIMMEDIATELY SO THERE IS NO NEED FOR ""RUN"". DELETE THE LOW MEMORYCOPY WITH ""NEW"" AND WRITE OR LOAD THE PROGRAM TO BE DEBUGGED.ACS-DEBUG CAN BE RUN AT ANY TIMEBY ""RAND USR 27467""."
173 PRINT "REMEMBER THAT ACS-DEBUG WORKS ENTIRELY IN DECIMAL. ENTER NUMBERS NORMALLY AND CONFIRM THEENTRY WITH NEWLINE. THE NUMBER CAN ONLY BE DELETED BY RUBOUT BEFORE NEWLINE IS PRESSED. THE SCREEN WILL CLEAR AND THE NUMBER CAN BE RE-ENTERED."
174 PRINT AT 21,0;"COPYRIGHT (C) ACS SOFTWARE 1982."
200 STOP
210 SAVE "ACS-DEBU[G]"
220 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.




