Reader 1 is a BASIC program that walks through the current program’s own tokenized BASIC storage in memory, displaying each byte’s address, decimal value, and printable ASCII representation. It reads the start-of-BASIC address from system variable PROG (held at addresses 23635–23636) and the address of variables (VARS, at 23627–23628) to determine where the program ends. Bytes with values below 16 or above 23 are displayed as characters using CHR$; values in the range 16–23 (which correspond to embedded control codes such as AT, TAB, and similar tokens with following parameter bytes) are labeled as unprintable. The program loops through each byte sequentially, incrementing the pointer and halting when it reaches the VARS boundary.
Program Structure
The program is a short sequential loop with no subroutines. Lines 10–15 initialize two pointers from system variables, lines 20–40 form the main display loop, and line 9000 is a standalone save command. The overall flow is linear:
- Lines 10–15: Read system variables to establish the byte-walk range.
- Line 20: Peek the current byte at the pointer address.
- Line 25: Print address and value; branch on printability.
- Line 30: Print the unprintable label (reached by fall-through when the condition in line 25 is false).
- Line 35: Advance the pointer; stop if the VARS boundary is reached.
- Line 40: Loop back to line 20.
System Variable Usage
The program reads two pairs of system variables to bound its walk:
| Variable | Addresses | Role |
|---|---|---|
p (PROG) | 23635–23636 | Start address of the BASIC program area |
v (VARS) | 23627–23628 | Start address of the variables area (end of program) |
Both are read as 16-bit little-endian values using the standard idiom PEEK low + 256 * PEEK high. The walk therefore covers exactly the tokenized program bytes, stopping before the variables area.
Printability Test
Line 25 uses the condition IF o<16 OR o>23 to decide whether a byte can be shown with CHR$. Values 16–23 are the embedded in-line parameter codes (such as AT, TAB, INK, PAPER, BRIGHT, FLASH, INVERSE, and OVER) which are followed by one or two data bytes in the token stream and would produce garbled or missing output if passed directly to CHR$. Bytes outside that range are considered safe to display as characters. Note that values 0–15 include newline markers and other control codes that are also non-printable in a conventional sense, so the test is a practical approximation rather than a fully rigorous printability filter.
Key BASIC Idioms
- Compound line with conditional: Line 25 puts the
PRINTand theIFon a single line, using the colon separator. When the condition is true theGO TO 35skips line 30; when false, execution falls through to the “UNPRINTABLE” branch — a common ZX BASIC branching pattern. - 16-bit pointer arithmetic: Both pointers are reconstructed from pairs of PEEKed bytes with
PEEK addr + 256 * PEEK (addr+1), which is the standard technique for reading 16-bit system variables. - Boundary check before increment: Line 35 increments
pfirst and then checks againstv, meaning the byte at the very last address before VARS is processed but the VARS byte itself is never read.
Self-Referential Nature
Because PROG points to the start of the running program itself, Reader 1 is examining its own token stream as it executes. This means the output includes the tokenized bytes of its own lines, making it a self-describing diagnostic tool. The large line-number gap between line 40 and the SAVE at line 9000 is a deliberate separation to keep the save command visually and logically isolated from the operational code.
Potential Anomalies
- The
SAVE "READER 1" LINE 0at line 9000 referencesLINE 0. Line 0 does not exist in the program; this is a known technique that causes the loaded program to start execution at the first available line (line 10) rather than indicating an error. - The display column layout relies on fixed
TABstops (8 and 16), which could overflow or misalign for addresses above 99999 or byte values printed withCHR$producing wide characters — though in practice both values stay within expected ranges.
Content
Source Code
10 LET p= PEEK 23635+256* PEEK 23636
15 LET v= PEEK 23627+256* PEEK 23628
20 LET o= PEEK p
25 PRINT p; TAB 8;o;:IF o<16 OR o>23 THEN PRINT TAB 16; CHR$ o:GO TO 35
30 PRINT TAB 16;"(UNPRINTABLE)"
35 LET p=p+1:IF p=v THEN STOP
40 GO TO 20
9000 SAVE "READER 1" LINE 0
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
