Reading Assembly

Before you start

Setup

You need no toolchain to use this site — every snippet compiles in the browser. But assembly is the one subject where the instrument can lie to you, so it is worth knowing what each one actually measures.

The minimum

Nothing. Every C and Rust snippet here has x86-64 andARM64 buttons that compile it on Compiler Explorer and show you the assembly. Install the rest when you want to check your own code rather than mine.

The instruments

ToolAnswersLies about
Compiler ExplorerWhat did the compiler emit?Your machine. It targets a generic CPU, not your M1.
objdump -d / otool -tvWhat is in this binary, on this machine?Nothing — but it shows the linked result, not per-function source mapping.
llvm-mcaThroughput and port pressure for a blockCaches and branches. It models the pipeline, not memory.
perf (Linux) / Instruments (macOS)Where time actually wentNothing, and this is the only one that measures reality.
uops.infoMeasured latency/throughput per instruction per microarchitectureYour specific chip, unless you pick the right one.

That last column is the point. Lesson3.1 is entirely about not mistaking the instrument for the territory, and lesson6.2 is about the one tool that measures rather than models.

On your own machine

You are on an Apple M1, which is ARM64. That is a real advantage: half of this course is ARM64, and you can disassemble it natively.

# compile without assembling, and look
clang -O2 -S -o - example.c | less

# or build and disassemble the real thing
clang -O2 -c example.c -o example.o
objdump -d example.o        # llvm objdump, ARM64
otool -tv example.o         # the macOS native tool

For x86-64 on an M1 you want Compiler Explorer rather than local tools — cross-assembling is possible but the setup cost is not worth it for reading.

Syntax: you will meet both

x86-64 has two assembly syntaxes for the same instructions, and the operand order is reversed between them. This site usesIntel syntax throughout, because it is what Compiler Explorer defaults to and what most documentation uses.

Intel (this site)AT&T (gcc default, gdb)
Directionmov dst, srcmov src, dst
Move 5 into raxmov rax, 5movq $5, %rax
Registersrax%rax
Constants5$5
Memory[rdi+8]8(%rdi)
Widthimplied by registersuffix: movq, movl

If you ever read assembly that looks backwards, that is why. In gdb,set disassembly-flavor intel.

One habit worth building

When a Predict box asks how many instructions something becomes, write a number before you press a compile button. Not “a few” — an actual number. Being wrong by 10× is the most useful thing that can happen to you here, and it only happens if you commit first.

Ready?0.1 — Why you will never write this.