Skip to content
Game 0 Unit 2 of 16 1 hr learning time

LD Is Not LET

Meet the registers — the handful of physical, 8-bit stores inside the CPU. Move a value from A into B and back again, and watch the border prove it made the trip.

13% of Meet The Machine

Last time you sent a number to the border and met the build-run loop. You used a register — A — without properly meeting it. Let's meet it now, because this is the first place the machine stops behaving like the language you came from.

In BASIC, LET a = 5 gave you a variable, and you could have as many as you liked — score, lives, name$, on and on. The CPU is not so generous. It has a handful of registers — small stores inside the chip itself — and that's all. Their names are fixed: A, B, C, D, E, H, L. You don't declare new ones. You learn to orchestrate the few you have.

And each one holds a single 8-bit number: 0 to 255, nothing larger. A register isn't a roomy named box; it's a tiny slot with a hard limit. That constraint shapes everything you'll write.

What you'll see by the end

The Spectrum's default screen surrounded by a solid cyan border.
A cyan border — colour 5, brought home through B. The border is the visible proof; the real show is the registers changing step by step.

A cyan border — colour 5. But the colour isn't the point this time. The point is how the 5 got there: it travelled from A into B, survived us wiping A, and came back. The border is just the proof you can see. The real show is in the register view — open it in your emulator and watch A and B change step by step.

LD just moves a number

There's one new idea here, and it's LD — "load". Despite the name, it doesn't "load" in any grand sense; all it does is move a number. Into a register from a literal (ld a, 5), or from one register into another (ld b, a). That's the whole instruction.

To prove a value moves between registers — instead of just trusting it — we send 5 on a round trip:

; ============================================================================
; PRIMER — Beat 2: LD Is Not LET
; ============================================================================
; In BASIC, LET a = 5 gave you as many named variables as you liked. The CPU
; doesn't work that way. It has a *handful* of registers — physical stores
; inside the chip, each holding one 8-bit number (0 to 255). Their names are
; fixed: A, B, C, D, E, H, L. You don't make more; you orchestrate these few.
;
; LD means "load", and all it ever does is move a number — into a register,
; or from one register to another. To prove a value really moves, we take it
; on a round trip and watch it come back:
;
;   1. Put 5 into A.            (5 = cyan)
;   2. Copy A into B.           (now B holds 5 too)
;   3. Wipe A back to 0.        (A = 0; if we stopped here the border'd be black)
;   4. Copy B back into A.      (A = 5 again — the 5 was safe in B all along)
;   5. Show A on the border.    (cyan proves B kept our 5)
;
; Open the register view in Emu198x and watch A and B change at each step.
; The border is just the visible proof; the registers are the lesson.
; ============================================================================

            org     32768

start:
            ld      a, 5             ; put 5 into A           (5 = cyan)
            ld      b, a             ; copy A into B          (B now holds 5 too)
            ld      a, 0             ; wipe A                 (A = 0; B still holds 5)
            ld      a, b             ; copy B back into A     (A = 5 again, from B)
            out     ($FE), a         ; show A on the border   (only A can do OUT)

.loop:
            halt
            jr      .loop

            end     start

This is last unit's program with three lines added in the middle. Follow A and B down the steps:

After…AB
ld a, 55
ld b, a55
ld a, 005
ld a, b55

We deliberately wipe A to 0, then bring the value back from B. The border ends up cyan — so the 5 must have been safe in B the whole time. That's the proof the copy was real.

Why copy back into A just to show it? Because the out instruction only ever sends A — never B or the others. It's one of the chip's fixed rules; just accept it for now. It's also what makes the round trip prove anything: the 5 had to come home through B.

Assemble and run

Same loop as before — change, build, run:

pasmonext --sna registers.asm primer.sna

Load primer.sna in your emulator with a register view open, and watch A and B move through the table above before the border settles on cyan.

Try this: too big to fit

Change ld a, 5 to ld a, 300, assemble, and run. Now look at A in the register view: it reads 44, not 300. A register holds 8 bits — 0 to 255 — and 300 doesn't fit, so the machine keeps only the low 8 bits (300 − 256 = 44). And notice what didn't happen: no error, no warning. The assembler let it through; the machine kept the bits that fit and carried on. The tools won't catch this for you — a theme we'll return to.

Try this: a longer trip

Send a value through three registers before showing it — A into B, B into C, then C back into A and out it. It's the round trip with one more hop (and a different colour to tell them apart):

One more register in the chain: A → B → C → A
+10-23
11 ; ============================================================================
2-; PRIMER — Beat 2: LD Is Not LET
2+; PRIMER — Beat 2, "Try this: a longer trip"
33 ; ============================================================================
4-; In BASIC, LET a = 5 gave you as many named variables as you liked. The CPU
5-; doesn't work that way. It has a *handful* of registers — physical stores
6-; inside the chip, each holding one 8-bit number (0 to 255). Their names are
7-; fixed: A, B, C, D, E, H, L. You don't make more; you orchestrate these few.
8-;
9-; LD means "load", and all it ever does is move a number — into a register,
10-; or from one register to another. To prove a value really moves, we take it
11-; on a round trip and watch it come back:
12-;
13-; 1. Put 5 into A. (5 = cyan)
14-; 2. Copy A into B. (now B holds 5 too)
15-; 3. Wipe A back to 0. (A = 0; if we stopped here the border'd be black)
16-; 4. Copy B back into A. (A = 5 again — the 5 was safe in B all along)
17-; 5. Show A on the border. (cyan proves B kept our 5)
18-;
19-; Open the register view in Emu198x and watch A and B change at each step.
20-; The border is just the visible proof; the registers are the lesson.
4+; Send a value through THREE registers before showing it:
5+; A -> B -> C -> back to A -> border.
6+; Predict A, B and C at each step, then watch them in the register view.
7+; (6 is yellow.)
218 ; ============================================================================
229
...
2411
2512 start:
26- ld a, 5 ; put 5 into A (5 = cyan)
27- ld b, a ; copy A into B (B now holds 5 too)
28- ld a, 0 ; wipe A (A = 0; B still holds 5)
29- ld a, b ; copy B back into A (A = 5 again, from B)
30- out ($FE), a ; show A on the border (only A can do OUT)
13+ ld a, 6 ; put 6 into A (6 = yellow)
14+ ld b, a ; copy A into B
15+ ld c, b ; copy B into C
16+ ld a, c ; copy C back into A
17+ out ($FE), a ; show A on the border (only A can do OUT)
3118
3219 .loop:

Before you run it, predict A, B and C at each step — then open your emulator's register view and check. (6 is yellow.)

When it's wrong, see why

  • pasmonext says "Expected 'A' but…" on the out line. You tried to out a register other than A. Only A can do out ($FE), a — route the value back into A first.
  • The border is black, not cyan. The ld a, b step is missing or mistyped, so A was still 0 (from the wipe) when you showed it. Put the round trip back exactly as shown.
  • The border's the wrong colour. Check the number in ld a, … — and remember the border reads only the low 3 bits, so values above 7 repeat the eight colours.

What you've learnt

A register is a physical, finite 8-bit store — the CPU has only a handful (A B C D E H L) — and LD moves numbers between them.

What's next

This isn't a Spectrum quirk: nearly every CPU is built around a small set of registers — some have more, some fewer. You're learning how machines work, not a Spectrum trick. Next — Everything Is a Number — we look at what those bytes you're moving around are, and discover the machine doesn't know a letter from a colour from a number. They're all just bytes.