Skip to content

ZX81

The Sinclair ZX81 (1981) is one of the most minimal computers ever sold to consumers. At launch it cost £69.95 as a kit or £99.95 assembled — a machine that genuinely put computing within reach of almost anyone. It has a 3.25 MHz Zilog Z80, 1 KB of RAM, and a distinctive membrane keyboard. Despite its limitations, it sold over 1.5 million units and inspired countless programmers.

In the IDE, the ZX81 preset gives you a browser-based emulator and a Z80 assembler. There's no C compiler or BASIC compiler for the ZX81 in the IDE — assembly is the language of choice for anything beyond the built-in BASIC.

Languages in the IDE

Language Notes
Z80 assembly Primary language for performance code
ZX81 BASIC Built into the ROM — interpreted, line-numbered

Quick start

  1. Select ZX81 as the platform.
  2. Choose the Assembly preset.
  3. The emulator boots the ZX81 ROM — you'll see the familiar K prompt.
  4. Build and your program loads and runs automatically.

1 KB is not a typo

The unexpanded ZX81 has exactly 1024 bytes of RAM. Your program, the display file, the BASIC system variables, and the stack all share that 1 KB. Plan accordingly. A 16 KB RAM pack (emulated in the preset) unlocks far more headroom.

Hardware overview

CPU — Z80 at 3.25 MHz (with heavy contention)

The Z80 runs at 3.25 MHz, but the ZX81 uses a slow mode during display generation where the CPU is halted for most of each scanline while the ULA generates the video. In slow mode, the effective CPU speed is roughly 1/4 of nominal. Fast mode (display off) gives the full clock rate but a blank screen.

Many ZX81 programs compute in fast mode and only enable the display during vertical blank.

ULA — Video

The ZX81's video is simpler than the Spectrum's — pure black and white, character-based only. The display is 32×24 characters of 8×8 pixel tiles from the character ROM.

There are no hardware sprites and no colour at all. Graphics are done by putting character codes into the display file, often using the block graphic characters (codes 128–191) which give a crude but effective 2×3-block resolution per character cell.

Memory map

Range Contents
$0000–$1FFF ROM (8 KB — BASIC interpreter)
$4000–$43FF RAM (1 KB — the whole machine)
$4000–$400B System variables
~$400C BASIC program start
(end of BASIC) Display file (variable length)
(top of RAM) Machine stack

With 16 KB RAM pack:

Range Contents
$4000–$7FFF 16 KB RAM expansion
$4009 RAMTOP system variable — tells BASIC how much RAM it has

Display file

The ZX81 display is unusual — it's a variable-length area in RAM, not a fixed framebuffer. Each row ends with a NEWLINE byte ($76). The ULA reads this at interrupt time and shifts it out to the TV.

A full 32×24 display uses 793 bytes (32 chars + 1 newline per row × 24 rows + 1 HALT byte).

To write a character at row R, column C:

; System variable DFILE ($400C in small RAM) holds display file address
; Each row is 33 bytes: 32 chars + $76 (NEWLINE)
LD HL, ($400C)          ; Load DFILE address
LD DE, 33               ; Row stride (32 chars + 1 newline)
; Multiply R by 33 and add C...
; (see full example below)

In practice most ZX81 programmers either use a lookup table of row addresses or call the ROM print routine.

Key ROM routines

The ZX81 ROM provides useful routines you can call from assembly:

Address Routine Action
$0918 PRINT-CHAR Print character in A at current cursor position
$0A2A CLS Clear screen
$02BB DISPLAY-5 Generate 5 frames of display (slow mode)
$0340 SLOW Enter slow mode (display on)
$0420 FAST Enter fast mode (display off, full CPU speed)
; Call FAST mode, compute, then SLOW mode to show result
CALL $0420      ; FAST — display goes blank, CPU runs at full speed
; ... expensive computation ...
CALL $0340      ; SLOW — display returns, CPU slowed by display

Z80 assembly on the ZX81

All standard Z80 instructions work — see the Z80 assembly guide for the full language reference. ZX81-specific considerations:

Character codes

ZX81 character codes are not ASCII. The ZX81 has its own character set where:

Code Character
0 Space
1–11 Block graphics
28 "
29–37 Digits 0–9, .
38–63 Capital letters A–Z
128–191 Inverse block graphics
192–255 Inverse characters

To print HELLO, you'd put bytes $28, $24, $31, $31, $34 into the display file (H=0x28, E=0x24, L=0x31, L=0x31, O=0x34 in ZX81 codes).

Minimal program — write to display

; ZX81 — write "HELLO" at top-left of screen
; Assumes 16K RAM pack; load at $8000

        ORG $8000

start:
        LD HL, ($400C)  ; Load DFILE pointer (display file address)
        LD A, $28       ; ZX81 char code for 'H'
        LD (HL), A
        INC HL
        LD A, $24       ; 'E'
        LD (HL), A
        INC HL
        LD A, $31       ; 'L'
        LD (HL), A
        INC HL
        LD A, $31       ; 'L'
        LD (HL), A
        INC HL
        LD A, $34       ; 'O'
        LD (HL), A
        RET

        END start

Run from BASIC with: RAND USR 32768

Fast mode computation loop

; ZX81 — compute in fast mode, display result in slow mode

        ORG $8000

start:
        CALL $0420      ; Enter FAST mode

        ; Compute something
        LD B, 200
count_loop:
        DJNZ count_loop ; Waste some time

        CALL $0340      ; Enter SLOW mode (display returns)
        RET

        END start

ZX81 BASIC

ZX81 BASIC is included in the ROM and is available at the K prompt. It's similar to Spectrum BASIC but more limited — no colour commands, no sound commands (no speaker), and the character set is different.

Key points: - Line numbers required - PRINT AT r,c;"text" — print at row/column (0-based) - PLOT x,y — set a block graphic pixel (64×48 resolution grid) - POKE addr,val / PEEK addr — direct memory access - RAND USR addr — call machine code at address - LOAD "" — load from tape (or emulated tape in IDE)

10 PRINT AT 10,14;"HELLO"
20 FOR I=0 TO 63
30   PLOT I,23
40 NEXT I
50 GOTO 10

RAM management tips

With 1 KB, every byte matters:

  • Use fast mode for computation-heavy loops — the display consumes RAM for the display file. If you collapse the display to 0 rows (just the HALT byte), you reclaim ~793 bytes!
  • Collapse the display during intensive loops: set the display file to just $76 (NEWLINE/HALT) — 1 byte instead of 793.
  • Use block graphics for graphics — characters 128–143 (and their inverses) give 2×3 sub-character resolution, effectively 64×48 graphic pixels.
  • 16K RAM pack changes everything — with the emulated 16K pack enabled, you have room for real programs.

See also