# GCC Assembly **Reading generated assembly** is the ground truth when debugging performance—it shows exactly what the CPU will execute. Use `-S` to generate assembly, and `-fverbose-asm` to annotate it with source variable names. ```bash gcc -O3 -march=native -S -fverbose-asm hot_loop.c -o hot_loop.s cat hot_loop.s ``` The `.s` file contains x86-64 assembly (or ARM, depending on your target) with source annotations. Each `#` line is a comment mapping the following assembly back to source. **Example output (simplified):** ```asm # hot_loop.c:5: for (int i = 0; i < n; i++) xor %eax, %eax .L2: cmp %edx, %eax jge .L4 # hot_loop.c:6: result[i] = a[i] + b[i]; movl (%rcx,%rax,4), %r8d add (%r8,%rax,4), %r8d movl %r8d, (%r9,%rax,4) inc %eax jmp .L2 .L4: ``` `xor %eax, %eax` clears the loop counter. `cmp %edx, %eax; jge .L4` checks if `i >= n` and jumps to the end. `movl`, `add`, `movl` perform the computation. `inc %eax` increments the counter. This repeats until the condition exits. **Analyzing for performance:** 1. Count instructions in the hot loop—more instructions = slower per iteration 2. Look for unexpected memory operations—loads and stores are expensive 3. Check for branch instructions (`jmp`, `jne`)—branches can cause pipeline stalls 4. Verify vectorization happened—look for `vmovdqa`, `vpadd`, etc. (AVX instructions) **No vectorization?** If you expected `-O3 -march=native` to use AVX but see only scalar instructions, something blocked vectorization. Use `-fopt-info-vec-missed` to find out why. **Compiler explorer:** Use [godbolt.org](https://godbolt.org/) to paste C code and see generated assembly interactively. Tweak code, change optimization levels, and see the assembly change in real-time. Great for learning. **Cross-reference with perf:** After identifying a hot instruction in assembly, use `[[perf]] annotate` to see the actual sample counts on that instruction: ```bash perf record -g ./app perf annotate -s hot_function ``` This combines profiling data with source/assembly, revealing exactly which instruction is a bottleneck. **Disassembly of compiled binaries:** ```bash objdump -d ./app | grep -A 30 hot_function ``` This disassembles the compiled binary (no source annotations, but shows the actual machine code executed). **Optimization hints:** Strange assembly patterns sometimes reveal missed optimizations. Examples: - Multiple branches in a hot loop—use conditional moves (`cmov`) instead - Redundant memory operations—the compiler didn't eliminate dead stores - Excessive function calls—aggressive inlining would help