Variable Area

Date: 198x
Type: Program
Platform(s): TS 2068

This program dumps and decodes the entire variable area in human-readable form, walking through memory starting at the address stored in system variables VARS (23627–23628). It identifies all seven variable types — single-letter numerics, multi-character named numerics, numeric arrays, FOR-NEXT loop control blocks, strings, and string arrays — by inspecting the high three bits of each entry’s first byte. Numeric values are decoded from the Spectrum’s five-byte floating-point format, including the sign bit, biased exponent (offset 128), and mantissa reconstruction across bytes 2–5. The FOR-NEXT loop handler extracts the current value, limit, step, line number, and statement counter from the control block, displaying them with labeled column alignment using TAB.


Program Structure

The program is organized as a dispatcher with a main loop and a set of subroutines. Lines 10–70 form the main loop: they read the current byte at pointer p, determine the variable type from the upper three bits, and branch to one of six handlers. Line 25 detects the end-of-variable-area sentinel byte (128). Lines 100–650 are the six type handlers, and lines 800–940 are shared utility subroutines.

LinesRole
1–5Initialization: screen colors, dimension work array
10–70Main dispatch loop
100–120Handler: single-letter numeric variable (type 3)
200–270Handler: multi-character numeric variable (type 5)
300–330Handler: numeric array (type 4)
400–465Handler: FOR-NEXT loop control block (type 7)
500–550Handler: string variable (type 2)
600–650Handler: string array (type 6)
800–875Subroutine: read and decode 5-byte float/integer
900–945Subroutine: read array header (dimensions and total element count)

Variable Area Navigation

The starting address is fetched via PEEK 23627+256*PEEK 23628, which reads the two-byte system variable VARS. The pointer p is advanced manually after each field is consumed. This byte-by-byte traversal mirrors what the Spectrum ROM itself does when searching for variables.

Type Dispatch Mechanism

At line 30, p2 = INT(p1/32) extracts the top three bits of the first byte (equivalent to a right-shift by 5). The resulting value identifies the variable type:

  • p2=3 — single-letter numeric (bits 011)
  • p2=5 — multi-character numeric name (bits 101)
  • p2=4 — numeric array (bits 100)
  • p2=7 — FOR-NEXT loop control (bits 111)
  • p2=2 — string variable (bits 010)
  • p2=6 — string array (bits 110)

Five-Byte Floating-Point Decoder (Lines 800–875)

The Spectrum stores all numeric variables in a five-byte format. Subroutine 800 first reads five bytes into array b(). If b(1) is zero, the value is a short integer stored in b(3) and b(4), with b(2)=255 signaling a negative value (two’s complement adjusted by subtracting 65536).

For true floating-point values, b(1) holds the biased exponent (bias 128), b(2) holds the sign in its high bit plus the implicit leading mantissa bit, and bytes 3–5 hold the remaining mantissa. The reconstruction at line 855 iterates j=2 TO 5, accumulating b(j)/256^(j-1). After restoring the implicit bit and adjusting the exponent at line 860, the result is scaled by 2^b(1). The sign flag m is applied last.

Multi-Character Variable Name Decoding (Lines 200–260)

In the Spectrum variable area, multi-character names encode the first letter with bit 6 set (adding 64) and the last letter with bit 7 set (adding 128), while intermediate letters are stored as plain ASCII. The handler subtracts 64 from the first byte and 128 from the last byte to recover the original characters, printing them in sequence.

FOR-NEXT Loop Block Handler (Lines 400–465)

A FOR-NEXT control block stores five values in sequence: the current loop value, the limit (TO value), the step, the line number (two bytes), and the statement number within that line. The handler calls subroutine 800 three times to decode the floating-point current, limit, and step values, then reads the two-byte line number and one-byte statement index directly with PEEK.

Array Header Subroutine (Lines 900–940)

Subroutine 900 reads the two-byte total byte-length field, then the dimension count d, then iterates over each dimension’s two-byte element count. It computes the total number of elements t as a running product (line 920), and prints the dimension sizes separated by commas before the closing parenthesis. The pointer is left one byte before the first element so that subsequent loops calling subroutine 800 (which pre-increments p) land correctly.

Notable Techniques

  • The array b(5) (line 5) is reused on every call to subroutine 800, avoiding repeated variable declarations.
  • TAB columns are used consistently for value alignment: column 16 for numeric values, column 22 for labels, giving the output a structured columnar appearance.
  • The main loop uses GO TO 20 rather than a FOR loop, since the step between entries is variable-length and depends on the type just processed.

Bugs and Anomalies

  • String array elements (lines 610–640): The handler reads only one byte per element (CHR$ PEEK p), which is incorrect for multi-character string array elements. Each element in a string array occupies a fixed number of characters defined by the last array dimension, so only the first character of each element is shown.
  • Typo at line 60: The REM comment reads “string aray” (missing ‘r’), which is cosmetic only.
  • Floating-point sign bit handling (line 850): When b(2) is less than 128 the sign flag m is set to 0 (positive) and 128 is added back to b(2) to restore the implicit leading mantissa bit. This logic is inverted from what the comment might suggest but is arithmetically correct for the Spectrum’s format.

Content

Appears On

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 PAPER 0:BORDER 0:INK 9
   5 DIM b(5)
  10 LET p= PEEK 23627+256* PEEK 23628
  20 PRINT p; TAB 6;:LET p1= PEEK p
  25 IF p1=128 THEN PRINT TAB 7;"END OF VARIABLE AREA":STOP 
  30 LET p2= INT (p1/32)
  35 IF p2=3 THEN GO TO 100:REM number (single-letter name)
  40 IF p2=5 THEN GO TO 200:REM number (multi-character name)
  45 IF p2=4 THEN GO TO 300:REM number array
  50 IF p2=7 THEN GO TO 400:REM loop control
  55 IF p2=2 THEN GO TO 500:REM string
  60 IF p2=6 THEN GO TO 600:REM string aray
  70 STOP :REM error if this line is reached
 100 REM number:-
 105 PRINT CHR$ p1;
 110 GO SUB 800
 115 PRINT TAB 16;n
 120 LET p=p+1:GO TO 20
 200 PRINT CHR$ (p1-64);:REM first letter
 210 LET p=p+1
 220 LET p1= PEEK p
 230 IF p1 >=128 THEN GO TO 260
 240 PRINT CHR$ p1;:REM middle letters (if any)
 250 GO TO 210
 260 PRINT CHR$ (p1-128);:REM last letter
 270 GO TO 110
 300 PRINT CHR$ (p1-32);"(";
 305 GO SUB 900
 310 FOR k=1 TO t
 315 GO SUB 800
 320 PRINT TAB 3;"element #";k; TAB 16;n
 325 NEXT k
 330 LET p=p+1:GO TO 20
 400 PRINT CHR$ (p1-128);
 410 GO SUB 800
 420 PRINT TAB 9;"(LOOP)"; TAB 16;n; TAB 22;"Current"
 425 GO SUB 800
 430 PRINT TAB 16;n; TAB 22;"Limit (TO)"
 435 GO SUB 800
 440 PRINT TAB 16;n; TAB 22;"STEP"
 450 LET l= PEEK (p+1)+256* PEEK (p+2):LET s= PEEK (p+3):LET p=p+4
 455 PRINT TAB 16;l; TAB 22;"Line No."
 460 PRINT TAB 16;s; TAB 22;"Statement"
 465 GO TO 20
 500 PRINT CHR$ p1;"$"; TAB 16;
 510 LET l= PEEK (p+1)+256* PEEK (p+2):LET p=p+2
 520 FOR j=1 TO l
 530 PRINT CHR$ PEEK (p+j);
 540 NEXT j:PRINT 
 550 LET p=p+j:GO TO 20
 600 PRINT CHR$ (p1-128);"$(";
 605 GO SUB 900
 610 FOR k=1 TO t
 620 LET p=p+1
 630 PRINT TAB 3;"element #";k; TAB 16; CHR$ PEEK p
 640 NEXT k
 650 LET p=p+1:GO TO 20
 800 REM integer
 805 FOR j=1 TO 5
 810 LET p=p+1:LET b(j)= PEEK p
 815 NEXT j
 820 IF b(1) THEN GO TO 845
 825 LET n=b(3)+256*b(4):IF b(2)=255 THEN LET n=n-65536
 830 RETURN 
 845 REM floating point
 850 LET m=1:IF b(2)<128 THEN LET m=0:LET b(2)=b(2)+128
 855 LET n=0:FOR j=2 TO 5:LET n=n+b(j)/256^(j-1):NEXT j
 860 LET b(1)=b(1)-128
 865 LET n=n*2^b(1)
 870 IF m THEN LET n=-n
 875 RETURN 
 900 REM arrays
 905 LET p1= PEEK (p+1)+256* PEEK (p+2):LET p=p+3
 910 LET d= PEEK p:LET p=p+1
 915 LET t=1:FOR j=1 TO d
 920 LET el= PEEK p+256* PEEK (p+1):LET t=t*el:PRINT el
 925 IF d <>1 AND j <>d THEN PRINT ",";
 930 LET p=p+2:NEXT j:PRINT ")"
 940 LET p=p-1
 945 RETURN 

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top