This utility program walks through the BASIC program area in RAM, starting at memory address 26710, computing a simple checksum for each line. For each line, it reads the two-byte line number and the two-byte length field, then iterates over pairs of bytes in the line body, subtracting alternate bytes to produce a running total. The checksum and line number for each line are printed to a printer via LPRINT, formatted with TAB 6 for alignment. The loop terminates when it encounters line 9999, which is the program’s own final line.
Program Analysis
Program Structure
The program is entirely self-contained in lines 9988–9999, with 9988 and 9989 serving as title/author REMs. The main loop runs from 9991 to 9999, with GO TO 9991 at the end creating an unconditional loop that advances a memory pointer (loc) line by line through the BASIC program area.
Memory Layout Traversal
The program exploits the standard Sinclair BASIC line storage format. Each line in memory is laid out as:
- Two bytes: line number (high byte first)
- Two bytes: line length (low byte first, little-endian)
- length bytes: the line body
Line 9991 reads the line number as PEEK loc * 256 + PEEK (loc+1) (big-endian), and line 9992 reads the length as PEEK (loc+2) + PEEK (loc+3) * 256 (little-endian), both consistent with the Sinclair BASIC line format.
Checksum Algorithm
The checksum loop at 9993–9995 steps through the line body two bytes at a time, computing total = total + PEEK(a) - PEEK(a+1). This is an alternating add/subtract byte checksum rather than a simple sum or XOR, which gives it slightly different sensitivity to byte-pair swaps. It is a lightweight integrity indicator rather than a cryptographic hash.
Output Formatting
Line 9996 uses LPRINT to send output directly to a printer, printing the line number followed by the checksum value, with TAB 6 providing consistent column alignment between the two values.
Termination Condition
The loop checks IF linum=9999 THEN STOP at line 9998, halting when the traversal reaches the program’s own last line (9999). This is a self-referential termination: the program uses its own final line number as the sentinel. Because line 9997 advances loc before the check, the checksum for line 9999 itself is not printed (the GO TO at 9999 would never be reached after a STOP, but the check at 9998 fires first).
Notable Techniques and Potential Issues
- The hard-coded start address
26710at line9990assumes the BASIC program begins at a fixed location, which is only valid for a specific memory configuration. On systems where the program start address differs,locwould need to be set viaPEEKof the relevant system variable instead. - The checksum loop uses
STEP 2and accessesPEEK (a+1), so if the line body has an odd length, the final byte is paired with the first byte of the next line’s header — a potential off-by-one anomaly at line boundaries. - Using lines in the
9988–9999range keeps the utility at the very end of a program, minimizing interference with code it is designed to audit and making it easy to append to any existing listing. - No variable initialization for
totalpersists between iterations — it is reset to0at the start of each loop pass in line9991, ensuring per-line independence.
Variable Summary
| Variable | Purpose |
|---|---|
loc | Current memory address of the start of the line being examined |
total | Accumulator for the per-line alternating checksum |
linum | Line number of the current line |
length | Byte length of the current line’s body |
a | Loop index over byte pairs within the line body |
Content
Image Gallery
Source Code
9988 REM LINE CHECK
9989 REM by John Bell
9990 LET loc=26710
9991 LET total=0: LET linum=PEEK loc*256+PEEK (loc+1)
9992 LET length=PEEK (loc+2)+PEEK (loc+3)*256
9993 FOR a=(loc+4) TO (loc+length+2) STEP 2
9994 LET total=total+PEEK (a)-PEEK (a+1)
9995 NEXT a
9996 LPRINT linum;TAB 6;total
9997 LET loc=loc+length+4
9998 IF linum=9999 THEN STOP
9999 GO TO 9991
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.