Preface
You can write software for years today without ever meeting the computer it runs on.
That isn’t a criticism. It’s the whole point of the last forty years. Every layer we’ve added, from operating systems to frameworks to the cloud, exists so that you don’t have to think about the layer underneath. You ask for a file and a file appears. You ask for a thousand servers and they’re there by lunchtime. The layers work so well that it’s possible to build a career without ever wondering what they’re hiding.
And mostly, that’s fine. Until it isn’t.
Sooner or later, every programmer meets a problem the layers can’t explain. Something is slow for no reason anyone can find. Something fails on one machine and not another. Something works, and nobody on the team can say why. At that point you have two choices. You can treat the system as weather: unpredictable, occasionally hostile, best handled by trying things until the problem goes away. Or you can go down a layer and look.
More and more software is built the first way. We trust the layers because they’ve earned it, and we fill the gaps with folklore, copied answers and, increasingly, code that nobody in the room wrote. It runs. Ask why it runs and the room goes quiet.
There was a time when that question had an answer you could hold in your head.
In the early 1980s, a generation of children and adults sat in front of television sets plugged into small, cheap computers and typed. They typed listings out of magazines, line by line, and then spent the evening finding the line they’d typed wrong. Some of them wrote games in their bedrooms that ended up on the shelves of high-street shops. They poked numbers into memory to see what would happen, and sometimes what happened was that the machine crashed and they had to start again.
Those machines didn’t protect anyone from anything. There was no operating system worth the name, no memory protection, nothing between the programmer and the hardware but a little BASIC and a lot of curiosity. If something went wrong, it went wrong in a way you could find. If something was slow, the reason was somewhere in the machine, and the machine was small enough to search.
I’m not going to pretend that was better. It was harder, slower and far more frustrating, and the software it produced was a fraction of what a single phone runs today. Nobody needs to go back.
But something was learned in those bedrooms that’s easy to lose: the habit of asking what the machine is actually doing. Not what the documentation says it does, or what it did last time, but what it’s doing now, and why it has no choice. That habit doesn’t belong to any one decade. It works on a 1982 home computer and it works on a data centre. It’s just much easier to learn on the home computer, because there’s so much less of it.
That’s what this book is for. It uses one small machine from 1982, and a few of its neighbours, to show what’s underneath the layers: what a program is, what the processor sees, why time matters more than speed, and why the strange things computers do are never really strange once you can see all the parts.
You won’t come out of it able to write a game. You’ll come out of it able to ask better questions of every machine you meet afterwards.
This book is an attempt to preserve a way of thinking, not just a way of programming.