CS 181-AR

ZX Spectrum BASIC: A Modern Developer's Survival Guide

You can find the complete manual for ZX Spectrum BASIC in the resources section of this site.

Key Differences from others BASICs

Version for LLMs

If you're working with an LLM, this abbreviated version of the ZX Spectrum BASIC guide on the Wiki will help clue the LLM into the differences.

Program Structure

Typical of other 1980s BASICs, ZX Spectrum BASIC had the following structure:

  • Programs are composed of numbered lines (1-9999)
  • Line numbers determine execution order
  • No block structures or multi-line IF statements
  • No WHILE/UNTIL loops or other modern control structures
  • Statements in a line are separated by colons (:)
  • No procedures or multi-line functions
  • All variables are global (except in user-defined functions, which can only evaluate a single expression)

Variables

  • Plain numeric variables: letters and digits starting with a letter, spaces ignored
  • Single letter names are required all other kinds of variables, specifically:
    • String variables (e.g., a$)
    • Arrays, both numeric and string (e.g., n(10), v$(10,20))
    • FOR loop variables (e.g., FOR i=1 TO 10)
    • User-defined functions (e.g., DEF FN f(x) = x^2 + 1)
  • Case-insensitive
  • String in string arrays must have fixed length specified in DIM

Indexing

Arrays are 1-based, not 0-based and use parentheses for indexing, not square brackets.

DIM fib(10): LET fib(1) = 1: LET fib(2) = 1
FOR i = 3 TO 10: LET fib(i) = fib(i-1) + fib(i-2): NEXT i
FOR i = 1 TO 10: PRINT fib(i): NEXT i

You can use array syntax to access a specific character in a string:

LET a$ = "HELLO"
PRINT a$(5)  ' Prints "O"

String Slice Syntax

  • Many other BASICs access portions of strings using MID$ or similar, this is not how it works on the ZX Spectrum
  • Use the TO keyword with a range of characters to get a slice of a string—unlike slices in Python, the range is inclusive.
LET a$ = "HELLO"
PRINT a$(2 TO 4)  ' Prints "ELL"
LET a$(2 TO 4) = "IPP"  ' Changes a$ to "HIPPO"

Control Flow

  • IF/THEN only works for single statements
  • GOTO and GOSUB are primary control mechanisms
  • No ELSE clause - must use multiple IF statements
  • FOR/NEXT loops require single-letter control variables
  • THEN GOTO 1000 cannot be abbreviated to THEN 1000

Key Implementation Details

  • Line numbers determine execution order
  • Line editing and LIST work with line numbers
  • Lines can be deleted by entering just their line number (!!)
  • Variables cleared on RUN but not on GOTO
  • Numbers stored as five-byte floating point with one byte exponent and four byte mantissa
  • Approximately 9.5 significant digits accuracy
  • Range approximately 10^-38 to 10^38
  • String storage uses fixed lengths
  • No user-defined functions except via DEF FN

Essential Commands

Note: In the examples below, we use ' for comments for readability, but on the actual ZX Spectrum you must use REM for comments, or :REM if not at the start of a line.

Program Control

RUN           ' Start program from beginning
GOTO n        ' Jump to line n
GOSUB n       ' Call subroutine at line n
RETURN        ' Return from subroutine
STOP          ' Stop program execution
CONTINUE      ' Resume after STOP

Variables

LET x = 42    ' Assign value (LET is required)
DIM a(10)     ' Create numeric array 
DIM a$(10,20) ' Create string array (20 chars per string)

Input/Output

PRINT x       ' Print value
PRINT "Hi"    ' Print string
INPUT x       ' Get numeric input
INPUT a$      ' Get string input
INPUT "Prompt: ";x  ' Input with prompt

Control Structures

IF x=0 THEN PRINT "Zero"        ' Single line only
FOR n=1 TO 10                   ' Must use single letter
    PRINT n
NEXT n

10 IF x<0 THEN GOTO 50         ' Multi-line if requires GOTO
20 PRINT "Positive"
30 GOTO 60
50 PRINT "Negative" 
60 REM Rest of program

Common Pitfalls

  1. Forgetting LET in assignments
x = 5         ' SYNTAX ERROR
LET x = 5     ' Correct
  1. Using complex IF structures
' This won't work:
IF x>0 THEN
    PRINT "Positive"
ELSE
    PRINT "Negative"
ENDIF

' Must use:
10 IF x>0 THEN GOTO 40
20 PRINT "Negative"
30 GOTO 50
40 PRINT "Positive"
50 REM Continue...
  1. Variable name limitations
counter = 1     ' Invalid - no LET
FOR counter = 1 ' Invalid - must be single letter
FOR i = 1       ' Valid
  1. String handling gotchas
DIM a$(10)      ' Creates ONE string of fixed length 10
DIM a$(10,20)   ' Creates array of 10 strings, each length 20
LET a$ = "Long" ' Truncated or padded to match DIMed length

Best Practices

  1. Line Numbers

    • Start with line 10, increment by 10
    • Leave gaps for inserting code
    • Use round numbers (100, 200, etc.) for major sections
  2. Program Structure

    • 10-90: Initialization
    • 100+: Main program
    • 1000+: Subroutines
    • 9000+: Error handling
  3. Variable Names

    • Use meaningful single letters where possible
    • i,j,k for loop counters
    • x,y,z for coordinates

    For example: ```basic 10 REM Initialize variables 20 LET score = 0: REM Current player score 30 LET x = 128: REM Screen center X 40 LET y = 88 REM Screen center Y 50 FOR i = 1 TO 10: REM Main game loop 60 REM Rest of program...

  4. Error Handling

    • Keep track of error states manually
    • Use GOTO for error conditions
    • Add error checking before calculations

Remember: ZX Spectrum BASIC is very different from modern structured programming. Embrace GOTOs and line numbers—they're your friends here!

(When logged in, completion status appears here.)