1969, when neither C nor B existed — Unix was written in the words just above machine code
At the end of Episode 6 we said "below the escape route (intermediate code), there is ultimately assembly and the machine." Now we descend there. The stage is Bell Labs in 1969. It's an era when neither C nor B (Episodes 5 and 6) yet exist in sufficient form. Ken Thompson found a small, idle computer — a PDP-7 — and, in its assembly language alone, wrote the kernel, the shell, and the editor. Without using a single rung of the high-level-language ladder — this is Unix's bare starting point.
The immediate trigger was a great failure. Bell Labs had teamed with MIT and GE to build the ambitious OS Multics, but progress was slow, and in the late 1960s they withdrew (this Multics itself is covered in a bonus episode, at the very top of the lineage). With time on his hands, Thompson tried to port the space-travel game Space Travel, which he'd built on Multics, to the idle PDP-7 — and along the way he made a file system, made processes, and before he knew it, it had become an OS. At first it had no official budget from Bell Labs either.
On the PDP-7, Thompson (and later Ritchie too) wrote one thing after another in assembly language — the kernel, the command interpreter (shell), the editor, the assembler itself, and a set of small utilities. Here were born the concepts that are still the spine of Unix/Linux today: the hierarchical file system, processes, and device files. All of it in the words just above machine code.
Let's make clear what "written in assembly" means. What the machine actually executes is machine code — just a sequence of numbers (opcodes and addresses), which humans can barely read. Assembly language is simply that, with human-readable names attached to the numbers. Instructions get mnemonics like lac (load) and add (add); addresses get labels like start: and n:. The two correspond almost one-to-one.
And the program that mechanically replaces those names with numbers is the assembler. In the figure below, watch line by line as assembly is translated into machine code. Look only at the numbers afterward, and the meaning becomes utterly unreadable — that is "the world the machine sees."
C, B, BCPL, and intermediate code were all ladders for "writing in an easier language and having it translated." Assembly is the bottom rung of that ladder. It just sticks names on the machine's very instructions; there's almost no more room to escape to "some easier language." Below here is the bare machine — machine code as numbers, and the physics that runs it.
The ladder may run out, but the chicken and egg doesn't vanish. To turn assembly into machine code, you need an assembler. So what assembled that first assembler? Moreover, PDP-7 Unix included the assembler itself, written in assembly. Eventually Unix could reassemble itself with its own assembler (self-supporting) — the smallest self-hosting, at the assembly layer. But "the very first one" can't be made inside that ring (Episode 0). In the figure below, see that ring, and the question that remains outside it.
PDP-7 Unix eventually moved to the PDP-11 in 1970 (again in assembly), and, as we saw in Episode 5, was rewritten in C in 1972–73. Here one loop of the series closes — Episode 5's "C grew out of B" and this Episode 7's "the first Unix was assembly" tie together at the same knot, the 1973 move to C. We are now heading even further below that knot, toward the origin of the very first assembler.
(1) The instructions and octal codes in Figure 1 are a simplified example to convey the feel of the correspondence between assembly and machine code; they are not a strict reproduction of the actual PDP-7 instruction table (the PDP-7 was a small 18-bit-word machine, and mnemonics like lac/dac/tad/jmp are real). (2) "Assembly→machine code is almost one-to-one" is basically correct, but there are exceptions such as pseudo-instructions, macros, and multi-word instructions.
(3) The story of Unix's birth (Multics withdrawal → Space Travel → file system → OS) is a famous, oft-retold arc, but the details differ by source. (4) "The ladder runs out here" is a figure of speech; in reality there are layers even below assembly, inside the machine, such as microcode (covered in Episode 10). (5) Early on, the assembly itself was done on a different machine — that story is exactly Episode 8.
In 1969, at a Bell Labs that had withdrawn from Multics, Thompson, while porting Space Travel to an idle PDP-7, made a file system along the way, and it became the first Unix (named UNICS by Kernighan). Neither C nor B yet existed, and the kernel, shell, editor, assembler, and utilities were all written in the assembly language of the PDP-7. Here the spine of Unix — the hierarchical file system, processes — was born.
Assembly is the thinnest skin, just human-readable names (mnemonics and labels) stuck onto machine code (numbers unreadable to humans). What replaces them with numbers is the assembler. The "easy-mode ladders" of C, B, BCPL, and intermediate code have here descended all the way to the bottom rung. But the chicken and egg remains — what assembled the first assembler? PDP-7 Unix includes the assembler itself and self-hosts at the assembly layer, but the very first one lies outside the ring. Next time, the answer — the cross approach that assembled on a different machine and carried it on paper tape.
Print / save as PDF: ⌘+P (Ctrl+P on Windows). On screen, use "▶ Assemble" in Figure 1 to trace the assembly→machine code translation, and Figure 2 to follow the self-hosting of PDP-7 Unix's lowest layer. "Show the answer" reveals each solution.