None of these tools require prior tooling experience, and every one of them has a browser-only fallback in case you can't install software on your machine. The goal of this lesson is simple: by the end you'll have each tool open, you'll have produced your first piece of assembly, and you'll know what a raw byte dump looks like. That's the entire kit for the rest of the course.
The four tools, and what each is for
Different layers of the machine need different microscopes. You don't need them all at once — each tool shows up exactly when the topic does — but it's worth knowing the whole kit up front so nothing feels like it appears from nowhere.
| Tool | Used for | Browser-only fallback |
|---|---|---|
| Compiler Explorer (Godbolt) | Seeing the assembly your C compiles to (Sections 6, 10) | It is the browser tool — nothing to install |
| Logic simulator | Building gates, adders, a tiny CPU (Sections 4–5) | CircuitVerse (runs in-browser) |
| gcc/clang + gdb/lldb | Compiling and stepping real programs (most sections) | Compiler Explorer's execute pane, or an online gdb |
| Hex viewer | Reading raw bytes & endianness (Sections 3, 8) | An online hex editor, or print("%02x") in any language |
Compiler Explorer: C in, assembly out
Compiler Explorer — everyone calls it "Godbolt" after its creator, Matt Godbolt — lives at godbolt.org and needs nothing installed. You type C (or C++, Rust, Go…) into the left pane, pick a compiler, and the right pane shows the exact assembly that compiler produces. It's the single most useful tool in this course because it makes the invisible translation from your code to machine instructions completely visible.
Here's the function from this lesson's plan. Paste it into the source pane and choose a recent x86-64 gcc or clang compiler:
int add(int a, int b) {
return a + b;
}
With optimizations on (try the flag -O2 in the compiler-options box), the assembly is strikingly short:
add:
lea eax, [rdi + rsi] ; eax = a + b
ret ; return value is in eax
Don't worry about decoding this yet — that's Section 6's whole job. For now, notice three things. First, your two parameters arrived in registers named rdi and rsi, not on a stack. Second, the compiler was clever: it used lea ("load effective address"), an address-arithmetic instruction, to do a plain addition in one step. Third, the result leaves in eax. Every one of those choices is something you'll fully understand later — and you just watched the compiler make them.
In Compiler Explorer, the compiler-options box (top right) takes the same flags as the command line — -O0 for no optimization, -O2 for aggressive optimization. And the "Intel" vs. "AT&T" toggle changes the assembly syntax. This course uses Intel syntax, so flip it to Intel to match the examples.
Compiling and debugging locally
Godbolt is perfect for looking, but eventually you'll want to run code and poke at it while it runs. For that you need two command-line tools that almost certainly already ship with your system, or are one install away: a compiler (gcc or clang) and a debugger (gdb on Linux/Windows-WSL, lldb on macOS).
Let's prove they work. Save the same function plus a tiny main as add.c, then run two commands. The first compiles it; the second produces the assembly text file so you can compare it to what Godbolt showed you.
# 1. Compile to a runnable program and run it
gcc add.c -o add
./add # prints: 2 + 3 = 5
# 2. Emit assembly to add.s (the -S flag = "stop after compiling")
gcc -O2 -S -masm=intel add.c -o add.s
Open add.s in any editor and you should find the same add: label with a lea and a ret inside it. That match — your local toolchain producing what the web tool produced — confirms the setup is sound. (If gcc isn't found: on Debian/Ubuntu run sudo apt install gcc gdb; on macOS run xcode-select --install; on Windows install WSL or MSYS2. No install access? Compiler Explorer's Execute pane runs the program right in the browser.)
The debugger lets you freeze a program mid-flight and read its registers and memory — exactly the state this course spends sixteen sections explaining. A first taste:
gcc -g add.c -o add # -g keeps debug symbols
gdb ./add
(gdb) break add # pause when add() is called
(gdb) run
(gdb) info registers rdi rsi # peek at the two argument registers
(gdb) stepi # execute exactly one machine instruction
(gdb) continue # let it finish
We'll introduce debugger commands one at a time, right where they're useful — break, run, stepi, info registers, and x (examine memory) cover almost everything this course does. The point of running it today is just to confirm it launches and stops where you ask.
Reading a hex dump
The last skill in your kit isn't a program to install but a way of seeing: reading raw bytes printed in hexadecimal. Memory holds nothing but bytes, and a hex viewer shows those bytes two hex digits at a time. You'll lean on this constantly once we discuss integers, endianness, and memory layout — so let's decode one dump now.
Suppose a program stores the 32-bit integer 1 in memory and we dump the four bytes at its address. On a typical x86-64 machine you'd see this:
address bytes meaning
00400a10 01 00 00 00 the 32-bit integer 1
Wait — why is the 01 first, not last? Because x86-64 is little-endian: it stores the least-significant byte at the lowest address. The value is one, so the low byte is 0x01 and the three high bytes are zero. This will feel strange the first time and obvious by Section 3.8. The diagram below makes the byte order concrete.
You can produce a dump like this yourself without any special tool. In a terminal, xxd or hexdump -C will dump any file; or in code, printing each byte with a %02x format string does the same job in any language. Reading these takes thirty seconds of practice and then becomes second nature.
Reproduce Compiler Explorer's output on your own machine. Compile the lesson's add function locally with gcc -O2 -S -masm=intel add.c -o add.s, open add.s, and confirm the body of add: matches the lea/ret you saw in the browser. (No local compiler? Use Compiler Explorer's Execute pane instead and just confirm it returns 5.)
Show the answer
Save this as add.c:
int add(int a, int b) { return a + b; }
#include <stdio.h>
int main(void) { printf("%d\n", add(2, 3)); return 0; }
Running gcc -O2 -S -masm=intel add.c -o add.s produces an add.s whose function body is essentially:
add:
lea eax, [rdi + rsi]
ret
That's the same instruction Godbolt showed — proof your local toolchain matches the web tool. Minor differences (extra directives like .cfi_*, or a leading underscore on macOS) are normal: those are bookkeeping the assembler and linker need, not part of the actual computation.
In Compiler Explorer, which setting makes the assembly match this course's examples?
-O2 for optimized output, -O0 for the literal, unoptimized translation.A dump shows 01 00 00 00 for a 4-byte int. What value is it, and why is the 01 first?
0x01) is stored at the lowest address and the zero high bytes follow.- Compiler Explorer shows your C as assembly, live in the browser — use Intel syntax and the
-O2flag to match this course. - A logic simulator (or CircuitVerse online) is for building gates and a tiny CPU later.
- gcc/clang + gdb/lldb let you compile, run, and freeze real programs to inspect registers and memory.
- A hex dump is just bytes in base-16; on little-endian x86-64 the least-significant byte sits at the lowest address.
- Every tool has a browser-only fallback, so nothing here blocks you.