Syncsum is a utility that extracts machine code from a REM statement and relocates it to a reserved area just below RAMTOP, where it can then be called via USR. The program operates in two passes: the first run reserves space by lowering RAMTOP by 27 bytes (configurable via the variable R at line 10) and issues NEW to clear BASIC memory, and the second run (entered with GOTO 100) decodes and POKEs the machine code bytes into that reserved region. The machine code is stored in REM line 1 as pairs of shifted ASCII characters (each nibble encoded by subtracting 28 and treating the result as a hex digit), which the extraction loop at lines 110–140 decodes. Once installed, the routine can be invoked with PRINT USR 32741 (or the 1K/2K equivalents 17381 and 18405) to compute a checksum of a loaded program.
Program Analysis
Program Structure
The program is designed to run in two distinct passes, separated by a NEW command that clears BASIC memory while leaving the reserved area below RAMTOP intact.
- First pass (lines 6–50): Sets
FASTmode, reads the current RAMTOP from system variables at addresses 16388–16389, subtractsR(27) bytes, writes the new RAMTOP back, and executesNEW. - Second pass (lines 100–150, entered with
GOTO 100after reloading): Reads the (now-lowered) RAMTOP, decodes the 27 machine code bytes stored in REM line 1, POKEs them into the reserved region, then callsNEWagain to leave just the installed routine.
Line 60 (NEXT B) is never reached in normal execution — it acts as a guard or dead code following the NEW at line 50.
RAMTOP Manipulation
System variables at addresses 16388 (low byte) and 16389 (high byte) hold RAMTOP as a 16-bit little-endian value. Lines 20–40 lower RAMTOP by R bytes using integer arithmetic to split the new value back into its two bytes:
POKE 16388, RAMTOP - 256 * INT(RAMTOP / 256)— stores the low byte (equivalent to RAMTOP MOD 256).POKE 16389, INT(RAMTOP / 256)— stores the high byte.
The instructions in the REM at line 5 specify three possible USR addresses: 32741 for a 16K RAM pack, 17381 for 1K, and 18405 for 2K, corresponding to the different RAMTOP values produced by each configuration minus the 27-byte reservation.
Machine Code Encoding in REM
The 27 machine code bytes are encoded in REM line 1 as a sequence of 54 characters. Each byte is represented by two characters, each encoding one nibble. The decode formula at line 120 is:
X = ((PEEK(16509 + 5 + B*2) - 28) * 16 + (PEEK(16509 + 5 + B*2 + 1) - 28))
- Address 16509 is the start of the BASIC program area (D_FILE system variable, or equivalently the program start).
- Offset 5 skips the line header (2-byte line number + 2-byte length + 1-byte token for
REM). - Each stored character has 28 subtracted to recover its nibble value (0–15), giving two nibbles packed into one byte.
The decoded Z80 machine code from line 1 is: 21 7D 40 ED 5B 0C 40 06 00 7C BA 20 08 7D BB 20 04 48 06 00 C9 78 AE 47 23 18 EE. This appears to be a loop that computes a XOR-based checksum over a region of memory (likely the BASIC program), returning the result in the BC or A register for use with USR.
Key BASIC Idioms
- Two-byte PEEK arithmetic (
PEEK(addr) + PEEK(addr+1) * 256) is the standard idiom for reading 16-bit system variables. INT(x / 256)andx - 256 * INT(x / 256)substitute for the absent MOD operator when splitting a 16-bit value into bytes.- Using
NEWmid-program (line 50) to reset BASIC while preserving memory below the new RAMTOP is a well-established technique for installing persistent machine code routines.
Notable Techniques
| Technique | Lines | Purpose |
|---|---|---|
| Nibble-pair encoding in REM | 1, 120 | Stores machine code as printable characters offset by 28 |
| RAMTOP reservation via system variable POKEs | 20–40 | Carves out 27 bytes below RAMTOP for the routine |
Two-pass load-and-run with NEW | 50, 150 | Installs code while clearing BASIC overhead |
Configurable reservation size via R | 10 | Allows easy adjustment if the machine code size changes |
Anomalies and Notes
- Line 60 (
NEXT B) is unreachable dead code; execution never falls through line 50’sNEW. It may be a leftover from an earlier version or an intentional no-op placeholder. - The variable
Rat line 10 is hardcoded to 27, matching the exact byte count of the machine code in line 1. Changing the machine code without updatingRwould corrupt the installation. - The offset calculation
16509 + 5 + B*2assumes the program is loaded at address 16509, which is the default BASIC program start. If the system variable D_FILE differs, the extraction would read wrong bytes — though in normal use the reload guarantees a clean state.
Content
Source Code
1 REM 217D40ED5B0C4006007CBA20087DBB2004480600C978AE472318EE
2 REM
3 REM % % %S% %Y% %N% %C% %S% %U% %M% %
4 REM
5 REM TO OBTAIN SYNCSUM, LOAD THIS PROGRAM AND RUN IT THEN LOAD IT AGAIN AND ENTER "GOTO 100". THEN LOAD YOUR MAIN PROGRAM AND IF YOU HAVE A 16K RAM PACK, YOU CAN ENTER THE COMMAND PRINT USR 32741 (17381 FOR 1K OR 18405 FOR 2K). SYNCSUM SHOULD BE CONSTANT FOR EACH PROGRAM YOU HAVE.
6 FAST
7 REM
8 REM ENTER R AS THE NUMBER OF BYTES YOU WANT TO RESERVE ABOVE RAMTOP
9 REM
10 LET R=27
20 LET RAMTOP=PEEK (16388)+PEEK (16389)*256-R
30 POKE 16388,RAMTOP-256*INT (RAMTOP/256)
40 POKE 16389,INT (RAMTOP/256)
50 NEW
60 NEXT B
100 LET RT=PEEK (16388)+PEEK (16389)*256
110 FOR B=0 TO 26
120 LET X=((PEEK (16509+5+B*2)-28)*16+(PEEK (16509+5+B*2+1)-28))
130 POKE RT+B,X
140 NEXT B
150 NEW
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
