5.3.17 · D1Build Systems & Toolchain

Foundations — Disassembly — objdump, reading assembly

1,888 words9 min readBack to topic

Before you can read a single line of objdump output, a stack of small ideas must already be solid. This page builds every one of them from zero, in the order they depend on each other. If a term in the parent note ever felt hand-wavy, it is defined here.


1. The bit and the byte — the alphabet of the machine

The picture: imagine 8 light switches in a row. Each switch is a bit — up or down. The whole row of 8 switches is one byte. There are 256 distinct patterns those 8 switches can make.

Why the topic needs it: every instruction the CPU runs is stored as bytes. When objdump prints 48 83 ec 08, those are four bytes — four rows of switches. Disassembly is literally the art of reading these switch-patterns.

Figure — Disassembly — objdump, reading assembly

2. Hexadecimal — a shorthand for bytes

Why this tool and not plain decimal? One byte = 8 bits = a number from 0 to 255. Written in decimal that takes 1–3 digits of unpredictable width. But 8 bits split neatly into two groups of 4 bits, and each group of 4 bits is exactly one hex digit (4 bits = 16 values = one hex digit). So every byte is always exactly two hex characters — tidy and aligned.

The picture: split your row of 8 switches down the middle. The left 4 switches make one hex digit, the right 4 make another. 48 in the objdump line means the byte whose switches read 0100 1000.

Why the topic needs it: every column of objdump output — addresses, raw bytes, immediate values like 0x8 — is printed in hex. You cannot read a disassembly line without reading hex.


3. Machine code vs. assembly vs. source — three languages

Assembly and machine code are the same instructions — one is bytes, the other is the readable label for those bytes. There is a one-to-one map between them.

Figure — Disassembly — objdump, reading assembly

Why the topic needs it: disassembly is the arrow from machine code back to assembly. Compilation goes source → asm → machine code; disassembly runs the last arrow backwards. The Compilation Pipeline covers the forward direction. Because the source→asm step is not reversible (comments, variable names, and structure are lost), disassembly can only ever recover the assembly layer — never your original C.


4. The CPU, registers, and memory

The picture: registers are the few pencils on your desk (instant reach); memory is the giant filing cabinet across the room (slower, but vast). The CPU works on pencils and shuttles paper to/from the cabinet.

Figure — Disassembly — objdump, reading assembly

Why the topic needs it: every operand in disassembly is either a register (rbp, eax), a memory address ([rbp-0x4]), or an immediate constant (0x8). You must recognise all three on sight.


5. The instruction — opcode + operands

The picture: a sentence in imperative mood. "Add edx into eax." Verb first, then the things.

Why the topic needs it: this is exactly why you cannot find the next instruction by counting a fixed number of bytes. objdump does the hard work of decoding where one instruction ends and the next begins.


6. Operand notation — [...], immediates, and offsets

The picture: rbp is a house address written on paper. [rbp-0x4] means "walk to that house, then look 4 boxes back, and open it." Brackets = open the box.

Why the topic needs it: the whole add function in the parent note is a dance of loading from [rbp-0x…] into registers and back. Miss the brackets and you'll think a memory access is a number.


7. Object files, sections, and .text

Why the topic needs it: objdump -d disassembles only the .text section — because only code is meant to be read as instructions. Point objdump's -D at data and it will try to decode numbers as if they were instructions, producing nonsense. Knowing sections exist explains why.


8. The flags register and conditional jumps

The picture: after every subtraction the CPU flips a few status LEDs — a "was-zero" LED, a "was-negative" LED. cmp x, 5 subtracts x - 5 only to light these LEDs, then throws the number away. jle looks at the LEDs and jumps if .

Why the topic needs it: this is how every if and loop appears in assembly (cmp then a conditional jump). Without knowing flags exist, the branch logic looks like magic.


The prerequisite map

Bits and Bytes

Hexadecimal

Machine code vs asm

CPU registers and memory

Instructions opcode and operands

Operand notation brackets

Object file sections .text

Flags register and jumps

Disassembly with objdump

Each foundation feeds the next; the four arrows into Disassembly are the four skills you actually use per line: recognise the layer, read the operands, know it lives in .text, and follow the flags/jumps control flow.


Where these lead next

  • Calling Conventions (System V x86-64)which registers hold arguments and returns (builds on §4).
  • Stack Frames & The Stack Pointer — what rbp/rsp and [rbp-0x4] really organise (builds on §4, §6).
  • Compiler Optimization Levels — why -O0 and -O2 produce wildly different asm.
  • Debugging with GDB — using these same registers/addresses live.

Equipment checklist

How many bits are in one byte, and how many values can it hold?
8 bits; values (0–255).
Why is one byte always exactly two hex digits?
8 bits split into two groups of 4, and each group of 4 bits equals exactly one hex digit (16 values).
What is 0x1c in decimal?
.
What are the three language layers, top to bottom?
Source code (human) → assembly (readable instruction names) → machine code (raw bytes).
What is the difference between a register and memory?
A register is a tiny fast slot inside the CPU; memory is the huge numbered array of byte-boxes outside it.
What is eax in relation to rax?
eax is the low 32 bits of the 64-bit register rax — same slot, smaller view.
In add eax, edx, which part is the opcode and which are operands?
add is the opcode (verb); eax, edx are the operands (nouns).
Why can't you find the next x86 instruction by counting a fixed number of bytes?
x86 is CISC with variable-length (1–15 byte) instructions, so instruction boundaries vary.
What does [rbp-0x4] mean?
The value stored in memory 4 bytes below the address in rbp — the brackets mean "open the box at that address".
Which section does objdump -d disassemble, and why only that one?
.text — because only executable code is meant to be read as instructions; data would decode as garbage.
What does cmp x, 5 actually do to the CPU?
Computes x - 5, discards the result, and sets the flags register so a following conditional jump can read them.