Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Part III · What a computer does with a program

What this part is for

One program, followed the whole way: from the text you typed to instructions a processor is executing, with nothing in between left as magic.

Part II put your code at the address the machine starts from, which is the only situation in which a program simply is somewhere. Every other program gets there by a route, and the route turns out to be four separate programs, several file formats and a system call. This part walks it. On the way it has to answer what a number in memory actually is, because a program is data before it is instructions, and because the bugs that survive longest come from a value meaning something other than what its name suggests.

It sits before Part IV because a kernel is a program. You cannot usefully read one until you know what a program is, what a compiler leaves unfinished, and who finishes it. ch15 ends at exec, the system call that puts a program into a process, which is precisely where Part IV begins.

What it leaves out

How a compiler works. Parsing, intermediate representations, register allocation as a subject in its own right — none of it is here. This part asks only what the compiler produced and whether you can account for it. Why it chose one thing over another, and whether a better choice existed, is ch26, and it is in Part V because the answer is about cost.

Also left out: every object format and loader other than the one in front of you. What generalises is that a linker joins fragments, that some of a program’s bytes are not stored because they are known to be zero, and that something has to place the result in memory before it can run. The spelling is local; the structure is not.

Where to start

ch12, in order. This part is a single argument in four steps, and each chapter finishes a question the one before it left open: what the compiler produced and what it left unfinished; what the bytes in it mean; what the instructions in it do; and who fills in the unfinished parts and puts the result in memory.

If you already know ELF — the file format the rest of the part takes apart — and want the rest, ch13 stands alone reasonably well; it is about representation rather than tooling, and it is the chapter most likely to change what you think you know.

Which machine, and what it cannot tell you

Mostly xv6: compiled with the RISC-V cross-compiler, run under QEMU, disassembled and read. ch12 compiles the same source on both targets, because the claim it makes — that the stages are a property of the toolchain and not of the machine — only holds up if you watch it happen twice.

Nothing in this part is timed. Every figure here is structural: what a file contains, which instructions the compiler emitted, what a program printed. That costs the chapters nothing: a stage boundary is a fact about the toolchain and survives being observed under emulation, whereas a duration does not survive it at all.

Where this leaves you

Able to take a program you did not write, find out what it is made of, and read the part of it the processor actually sees.