JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

How a Computer Actually Runs Your Code

From the source file you type to the electrons in the CPU: a ground-up tour of the machine model, the abstraction stack, and the edit-compile-run loop, ending with a hello-world in C you can really run.

The machine, stripped to three parts

In the last guide we said systems programming means working close to the machine. So let us look at the machine. Strip away the screen, the keyboard, the fans, and what remains is astonishingly simple in outline: a processor that does arithmetic and makes decisions, a memory that holds numbers, and some input/output that lets the box talk to the outside world. Almost everything else — caches, buses, graphics cards — is an optimization or a convenience layered on top of those three. This three-part sketch is the von Neumann architecture, named after a 1945 design note, and it is the mental model every C programmer carries around.

The memory is the part to picture most carefully, because it is where your data lives. Think of it as one enormous numbered street of mailboxes, each box holding exactly one byte (eight bits, a number from 0 to 255). The number on a mailbox is its address. That is the whole idea behind memory as a byte array: when you later write `int x` in C, the language quietly picks a few neighbouring mailboxes and remembers the address of the first one. Addresses are why pointers will eventually feel natural rather than magical — a pointer is just a mailbox number written down.

Here is the move that makes this architecture so powerful, and it is worth pausing on: in a stored-program computer, the instructions of your program live in that same numbered memory, right alongside your data. The CPU does not know in advance which bytes are 'code' and which are 'numbers' — it simply reads from an address and treats what it finds as an instruction because you told it to start there. Program and data are the same kind of stuff. That single decision is what lets one machine run a word processor today and a compiler tomorrow.

The heartbeat: fetch, decode, execute

So how does the processor actually 'do' anything? It runs a tiny loop, billions of times a second, and that loop is the fetch-execute cycle. The CPU keeps a special register called the program counter that holds the address of the next instruction. Each turn of the loop: fetch the instruction from that address, figure out what it means, carry it out, and advance the program counter to the next instruction. Then again. And again. There is no master plan inside the chip — just this relentless three-beat rhythm.

  1. FETCH: read the instruction stored at the address in the program counter.
  2. DECODE: figure out what that bit pattern means — add, copy, jump, and which values it touches.
  3. EXECUTE: actually carry it out, changing a register or a memory location.
  4. ADVANCE: move the program counter to the next instruction, and loop. A jump simply sets the counter somewhere else.

Each instruction is itself just a pattern of bits — a small number that the chip is wired to interpret as 'add these two values', 'copy this from memory', 'jump to that address if the last result was zero'. To do their work, instructions use a handful of ultra-fast scratchpad slots inside the CPU called registers (names like rax, rsp, rip that you will meet in the assembly rung). Memory is the big numbered street; registers are the few notes the processor keeps in its hand. The art of speed, much later, will be about keeping the values you need in registers rather than fetching them from memory.

From your text to those bit patterns

Now the gap that systems programming is really about. You write `printf("hello\n");` — readable English-ish text. The CPU only ever runs those bit-pattern instructions. Something has to bridge the two, and that bridge is the difference between source code and machine code. Source code is for humans; machine code is the raw numbers the chip executes. A C compiler is the translator that turns one into the other, once, ahead of time, producing a finished file the machine can run directly.

That distinction between translate-once-then-run and translate-as-you-go is the heart of compiled versus interpreted execution, which the very next guide pulls apart properly. For now, hold one fact: C is compiled. Your `.c` file goes through the compiler and comes out the other side as an executable — a self-contained file of machine code the operating system can load and launch. Languages like Python instead ship an interpreter that reads and runs your source line by line every time. Different roads to the same CPU; we will walk both.

Why does anyone bother stacking these translations and layers? Because no human wants to hand-write bit patterns, and no one wants to rewrite their program for every chip. This is the whole point of the abstraction stack: hardware at the bottom, then machine code, then a language like C, then your application on top. Each layer hides the mess below it and offers a cleaner handle above. The skill of a systems programmer is being able to drop down a layer when something breaks — which is exactly why we are building from the metal up rather than from the app down.

Two worlds: your program and the kernel

One more boundary before we run anything, because it shapes everything later. When your `hello` program prints text, it does not poke the screen hardware itself. It asks the operating system to do it. The OS core — the kernel — is the one trusted program that actually touches the hardware: memory, disk, network, the terminal. Everything else, including your code, runs as an ordinary, untrusted citizen. That split is kernel space versus user space.

The reason for the wall is safety: if any program could write to any memory or any device, one bug would crash the whole machine. So the CPU itself runs in two modes — a privileged kernel mode and a restricted user mode — and a buggy or hostile user program can only ask, never seize. The asking is done through a special, deliberate boundary crossing called a system call, which we will study in detail in a later rung. For today, just register the shape: your code lives on one side of a guarded wall, the hardware on the other, and the kernel is the gatekeeper.

The loop you will live in, and a real hello-world

All of this comes together in the rhythm of actually programming: the edit-compile-run loop. You edit the source in a text file, you compile it with a tool to produce an executable, and you run that executable and watch what happens. When the output is wrong, you go back to edit. You will spin this loop thousands of times this year. The whole toolchain that does the compiling — preprocessor, compiler, assembler, linker — we will dissect in its own rung; for now treat `gcc` as a single magic translator.

So here is a real, complete, correct C program — the traditional hello-world. Read every line: `#include <stdio.h>` pulls in the declaration of `printf()`; `int main(void)` is the one function the system calls to start you off; `printf` asks the OS to write text; and `return 0` hands back a number that means 'I finished, and all was well'.

#include <stdio.h>

int main(void)
{
    printf("hello, world\n");
    return 0;
}

# build it, then run it:
#   $ gcc -Wall hello.c -o hello
#   $ ./hello
#   hello, world
hello.c, plus the two shell commands that compile and run it. The -Wall flag turns on warnings; get into the habit now.

Trace what just happened against the whole guide. The compiler turned that text into machine-code instructions in the executable `hello`. Running `./hello` asks the kernel to load those instructions into memory and point the program counter at the first one; the CPU then fetches and executes them one by one until `return 0` runs. That `0` becomes the program's exit status, a tiny report card the shell can read (check it with `echo $?`). You have now followed your code from text, through translation, across the kernel boundary, down to the fetch-execute loop, and back out as a number. The next guide takes the compiled-versus-interpreted fork in that road and explores where it leads.