Chapter 1 Summary and Quiz
Review the three levels of a program, the compilation pipeline, the anatomy of an instruction, the common instructions, and the two assembly dialects.
From C++ to assembly recap
You have completed the first chapter of this course. You started with a language the CPU cannot read at all and ended by generating and reading real x86-64 listings yourself. Let's review the key ideas from each lesson before you test yourself.
What Is Assembly, and Why Read It?
A program exists at three levels: the C++ source you write, the machine code the CPU actually executes, and assembly language in between, a human-readable spelling of machine code in which each instruction maps almost one-to-one onto a machine instruction. Reading assembly lets you see what your code really costs, verify the optimizer, debug the truly strange bugs, and understand the consequences of undefined behavior. Assembly is tied to a specific instruction set architecture; this course teaches x86-64, the most common and best-documented target.
The Vocabulary of Assembly
An instruction is a single command to the CPU, and instructions run top to bottom unless one jumps elsewhere. The mnemonic names the action (mov, add, ret); the operands after it are what it acts on, destination first in Intel syntax. An operand is one of three things: a register (a bare name like eax, a tiny fast slot inside the CPU), a memory location (written in square brackets, like -4[rbp]), or an immediate (a literal constant baked into the instruction). A label ends with a colon and names a location; an address is simply a numbered location in memory, and a pointer is a register holding one.
The Compilation Pipeline
Building a program is a four-stage pipeline: preprocess (-E) resolves #include and macros into a translation unit, compile (-S) translates that C++ into assembly and performs all optimization, assemble (-c) turns the assembly into machine code in an object file, and link combines object files and libraries into an executable. Assembly is the output of the compile stage: the last human-readable form of your program, captured after every optimization decision has been made.
Reading Your First Listing
An unoptimized function follows a fixed shape: the prologue (push rbp / mov rbp, rsp) sets up a stack frame, arguments are stored to stack slots and reloaded, a little real work happens, and the epilogue (pop rbp / ret) tears down and returns. C++ mangles function names into symbols like _Z6squarei; tools usually show the demangled form. Most of an -O0 listing is plumbing around one or two instructions of actual computation, like the imul eax, eax at the heart of square:
square(int):
imul edi, edi
mov eax, edi
ret
That is the same function at -O2, with all the plumbing optimized away.
The Common Instructions
About a dozen instructions cover most compiler output. mov copies a value; lea computes an address without touching memory. add, sub, and imul do arithmetic, leaving the result in the destination operand. cmp and test set the flags and keep no result; they exist to feed the jump that follows. jmp always jumps, while conditional jumps (je, jne, jl, jg, ...) act on the flags, so cmp and a jump travel as a pair. push, pop, call, and ret are the machinery of function calls, with the return value coming back in eax.
Intel vs AT&T Syntax
The same machine instructions have two spellings. Intel syntax (used in this course) writes dest, src with no prefixes and states sizes with keywords like DWORD PTR only when needed. AT&T syntax (the GNU default) reverses the operand order to src, dest, prefixes registers with % and immediates with $, encodes size as a mnemonic suffix (b/w/l/q), and writes memory operands as disp(base, index, scale) instead of brackets. Add -masm=intel to make GNU tools emit Intel syntax.
Generating Assembly Yourself
You have four ways to make listings. g++ -S stops the pipeline after the compile stage and writes a .s file; add -masm=intel and -fno-asynchronous-unwind-tables to clean it up, and always state the optimization level (-O0 for literal, source-shaped code; -O2 for what ships). objdump -d -M intel disassembles a finished binary when you have no source or need the final linked result. Compiler Explorer (godbolt.org) gives live, color-coded source-to-assembly mapping, and this site's editor has a live assembly panel so you can read the assembly of every exercise you write.
Key Terminology
- Machine code: The numeric encoding of instructions that the CPU executes directly
- Assembly language: A human-readable spelling of machine code, roughly one instruction per machine instruction
- Instruction set architecture (ISA): The specific processor family an assembly listing targets, such as x86-64
- Mnemonic: The short name of an instruction's action, such as
movoradd - Operand: What an instruction acts on; destination first in Intel syntax
- Register: A small, fast, named storage slot inside the CPU
- Memory operand: An operand in square brackets naming a location in RAM
- Immediate: A literal constant written directly inside an instruction
- Label: A name ending in
:that marks a location, such as a function start or jump target - Translation unit: The single block of pure C++ produced by the preprocessor for one source file
- Object file: Machine code produced by the assembler, not yet linked into an executable
- Name mangling: The encoding of a C++ function's signature into a symbol like
_Z6squarei - Prologue / epilogue: The stack-frame setup and teardown at the start and end of a function
- Flags: CPU status bits set by
cmpandtestand read by conditional jumps - Intel syntax / AT&T syntax: The two notations for x86-64; Intel is
dest, src, AT&T issrc, destwith%and$prefixes - Disassembly: Turning machine code in a binary back into assembly, e.g. with
objdump -d - Optimization level: The
-O0/-O2setting that changes the emitted assembly more than any other flag
Looking Forward
You can now recognise the shape of a listing, but so far the registers in it have mostly been names flying past. Chapter 2 slows down and studies the machinery itself: the sixteen general-purpose registers and their conventional roles, why the same register appears as rax, eax, ax, or al, and exactly how mov, the arithmetic instructions, addressing modes, and lea work. That foundation is what turns pattern-spotting into genuine reading.
Create an account to track your progress and access interactive exercises. Already have one? Sign in.
Chapter 1 Summary and Quiz - Quiz
Test your understanding of the lesson.
Lesson Discussion
Share your thoughts and questions
No comments yet. Be the first to share your thoughts!