The Zilog Z80 is an 8-bit microprocessor designed by Federico Faggin and Masatoshi Shima in 1976, running at 2.5 to 8 MHz depending on the variant, and occupying the specific category of technology that is not the most powerful, not the most elegant, not the most influential in retrospect, but the one you remember with the ache of a first love, because it was the first machine you understood completely.
The Z80 was the brain of the ZX Spectrum, the MSX standard, the Amstrad CPC, the TRS-80, the Pac-Man arcade cabinet, and approximately every CP/M business computer that existed before the IBM PC made everyone forget that business computing existed before 1981. It was not the most popular 8-bit CPU (the 6502 sold more units through the C64 and NES). It was not the most constrained (the 6502 was simpler). It was the one that, for a particular generation of European programmers, was the first.
First loves are not chosen for their technical specifications. First loves are chosen by circumstance — by which computer your father bought, by which magazine was on the shelf, by which friend had which machine. The Z80 was a first love because the ZX Spectrum was cheap and the Spectrum was cheap because Clive Sinclair was stubborn and Sinclair was stubborn because he believed computing should be affordable and accessible and — here the chain of cause and effect becomes emotional rather than technical — a boy in Lisbon got a TS2068 and the TS2068 had a Z80 and the Z80 had registers that the boy would remember for the rest of his life.
“The binary works. The binary has always worked.”
— The Lizard, who was born on a Z80-powered power supply brick, The Databases We Didn’t Build
The Registers
The Z80 has a register set that is, compared to the 6502’s spartan three, positively luxurious:
- A (the accumulator) — where arithmetic happens
- F (flags) — carries, zeros, signs, the emotional state of the last operation
- B, C — general purpose, often used as a counter (DJNZ, the loop instruction, decrements B)
- D, E — general purpose, often used as a destination pointer
- H, L — general purpose, but special: HL is the primary 16-bit pointer, the register pair that addresses memory, the workhorse
- IX, IY — index registers, 16-bit, with offset addressing. The eccentric uncles: rarely visited, enormously useful when needed, slightly slower than HL because of the extra prefix byte
- SP — stack pointer
- PC — program counter
- I, R — interrupt vector and refresh register (the R register increments with every instruction for no reason any programmer ever cared about, but it’s there, reliably counting nothing)
And then — the Z80’s secret — a complete second set of A’, F’, B’, C’, D’, E’, H’, L’, accessible only through the EXX and EX AF,AF’ instructions, which swap the primary and alternate registers in a single cycle. This was Faggin’s answer to fast interrupt handling: instead of pushing registers to the stack, swap to the alternate set, handle the interrupt, swap back. Four cycles instead of twenty-eight.
The alternate register set is the Z80’s most elegant feature and its most characteristic one. It is hidden. It is fast. It solves a specific problem with the minimum possible mechanism. It is the hardware equivalent of the Lizard’s philosophy: do the thing that works, do it with the minimum machinery, do not explain yourself.
The Instruction Set
The Z80 has 158 instructions (not counting the undocumented ones, which every serious Z80 programmer uses and none of the documentation acknowledges). The instruction set includes:
- Block operations: LDIR (copy block), CPIR (search block), INIR/OTIR (block I/O)
- Bit operations: SET, RES, BIT — set, reset, and test any bit of any register
- Relative jumps: JR — branch with a signed 8-bit offset, saving a byte compared to JP
- DJNZ — decrement B and jump if not zero, a hardware loop instruction
The instruction set fits on both sides of a single sheet of paper. This is important. This means a child can memorise it. Not the reference card — the entire instruction set. Every instruction, every addressing mode, every timing. The Z80 is the last major processor whose instruction set a human being can hold in their head, complete, without simplification.
This matters because holding the instruction set in your head means knowing what the machine can do. Not looking it up. Not consulting a reference. Knowing. The way a carpenter knows their tools. The way a musician knows their instrument. The Z80 programmer knew, at every moment, every instruction available, every cycle each one cost, every register each one affected. The program was not an abstraction over the hardware. The program was the hardware, expressed in mnemonics.
The 68000 was more powerful. The 68000 could not be memorised — too many instructions, too many addressing modes, too many registers. The 68000 required a reference manual. The Z80 required a sheet of paper, and after six months, not even that.
The First Assembly
Every Z80 programmer remembers their first assembly language program. Not their first BASIC program — BASIC was the porch. Assembly was the house.
The first program was probably something like:
LD HL, message ; point to the string
loop: LD A, (HL) ; load the next character
CP 0 ; is it the terminator?
JR Z, done ; if yes, stop
CALL put_char ; print the character
INC HL ; next character
JR loop ; repeat
done: RET
Eight instructions. Each one does exactly one thing. Each one takes a known number of cycles. The program loads a byte, checks if it’s zero, prints it if not, moves to the next byte, and repeats. There is no ambiguity. There is no hidden behaviour. There is no garbage collector, no runtime, no framework, no container, no orchestrator. There are eight instructions, and they do what they say, and the programmer knows what they do because the programmer wrote them and the programmer can hold the entire Z80 instruction set in their head.
This is the experience that Rust takes away: the directness. The intimacy with the machine. The knowledge that the thing you wrote is the thing that runs, with no translation layer, no optimisation pass, no borrow checker rearranging your intent into something the type system finds acceptable.
And this is the experience that Go, imperfectly and at a much higher level of abstraction, tries to preserve: the code does what it says. The if err != nil is there because the error is there. The function is twelve lines because the operation takes twelve steps. There is no magic. There is only what you wrote.
CP/M and the Business Z80
The Z80 was not only a home computer processor. Before the IBM PC, the Z80 was the business processor. CP/M — Gary Kildall’s operating system, the one that IBM considered before choosing DOS — ran on Z80 machines. WordStar, dBASE, Turbo Pascal (its first version) — all Z80, all CP/M.
This is often forgotten. The narrative of personal computing typically begins with the IBM PC in 1981. The reality is that personal computing began with the Z80 and CP/M in the late 1970s, in offices that used 8-bit machines for word processing, spreadsheets, and databases, years before IBM decided the market existed.
The IBM PC killed CP/M. The Z80 survived, in Spectrums and MSX machines and arcade cabinets, long after its business career ended. The Z80 outlived the company (Zilog was acquired, restructured, and absorbed). The Z80 outlived the platform (CP/M is a footnote). The Z80 outlived the era. The Z80 is still manufactured, in CMOS variants, for embedded systems.
First loves do not die. They change form.
The Emotional Register
There is no rational reason to feel affection for a silicon chip. The Z80 does not know it is loved. The Z80 does not know anything. It is a collection of transistors that responds to electrical signals according to the rules Federico Faggin etched into it in 1976.
And yet.
The registers have names. A, B, C, D, E, H, L. The programmer who learned on a Z80 remembers these names the way a musician remembers the strings. HL was the pointer that addressed the world. A was where the work happened. B was the counter that DJNZ decremented. The alternate set (A’, B’, C’, D’, E’, H’, L’) was the secret room — swap in, do the work, swap back, and nobody knew you were there.
The Z80 was the first machine a boy in Lisbon understood completely. Not used — understood. Every register, every flag, every instruction, every timing. The understanding was total, the way only a first understanding can be, before the world gets complicated, before the 68000 arrives with its thirty-two-bit ambitions, before the Amiga’s blitter makes scrolling too easy, before Go and Rust and Java and the entire enterprise edifice that the Z80 could not have imagined and would not have approved of.
The Z80 ran at 3.5 MHz. The M1 MacBook runs at 3.5 gigahertz — a thousand times faster. The M1 cannot be understood completely. No one holds its instruction set in their head. No one knows, at every moment, what every transistor is doing.
The Z80 could be known. That was its gift. Not power. Knowability. The first machine you understood completely is the machine that teaches you what understanding feels like, and every machine after that is measured against it, and every machine after that falls short, not in capability but in intimacy.
LD A, first love.
RET.
