Question
How can I generate assembler output from C or C++ source code using GCC?
If I want to analyze how a program is being compiled, what command should I use to view the emitted assembly code?
Short Answer
By the end of this page, you will understand how to ask GCC to stop after compilation and write the generated assembly to a file. You will also learn the most useful command-line flags for producing readable assembly, how optimization levels affect the output, and how developers inspect assembly when debugging performance or compiler behavior.
Concept
GCC turns C or C++ source code into machine code through several stages:
- Preprocessing – handles
#include,#define, and conditional compilation - Compilation – translates source code into assembly
- Assembly – converts assembly into object code
- Linking – combines object files and libraries into an executable
If you want to inspect the assembly that GCC generates, you usually want to stop the build process after the compilation stage and save the assembly text to a file.
The main flag for this is:
gcc -S file.c
or for C++:
g++ -S file.cpp
The -S option tells GCC:
- compile the source
- generate assembly output
- do not assemble it into an object file
This matters because assembly is often the easiest way to see:
- how high-level code maps to CPU instructions
- whether functions were inlined
- whether loops were optimized
- how variables are stored or passed
- how different optimization flags change the generated code
In real programming, inspecting assembly is useful for:
- performance tuning
- understanding compiler optimizations
- debugging unexpected low-level behavior
- comparing different code patterns
- learning how C/C++ features work under the hood
Mental Model
Think of GCC like a factory pipeline.
- Your C/C++ source file is the raw material.
- GCC passes it through several machines.
- One machine produces a human-readable low-level blueprint: assembly.
- Another machine turns that blueprint into binary object code.
Using -S is like telling the factory:
“Stop after creating the blueprint, and give me that file instead of the final product.”
That blueprint helps you understand exactly what GCC plans to tell the CPU to do.
Syntax and Examples
The core command is:
gcc -S program.c
This creates a file named:
program.s
For C++:
g++ -S program.cpp
Example 1: Basic C example
Source file:
int add(int a, int b) {
return a + b;
}
Compile to assembly:
gcc -S add.c
Output file:
add.s
Example 2: Choose the output filename
gcc -S main.c -o main.asm
This writes the assembly to main.asm instead of the default main.s.
Example 3: Include optimization
gcc -S -O2 main.c
Step by Step Execution
Consider this file:
int square(int x) {
return x * x;
}
Command:
gcc -S square.c
What happens step by step
- GCC reads
square.c. - It preprocesses the file.
- It compiles the code into assembly instructions.
- Because you used
-S, GCC stops there. - It writes the assembly text into
square.s.
Likely generated file
The exact output depends on your platform, GCC version, and optimization settings, but it may look roughly like this:
.file "square.c"
.text
.globl square
.type square, @function
square:
imull %edi, %edi
movl %edi, %eax
ret
How to read it at a high level
square:marks the function label.imullmultiplies the input by itself.movlplaces the result into the return register.retreturns from the function.
Real World Use Cases
Developers inspect GCC assembly output in many practical situations.
Performance tuning
You want to know whether a loop was optimized well:
for (int i = 0; i < n; i++) {
sum += data[i];
}
Looking at assembly can show whether GCC:
- unrolled the loop
- used registers efficiently
- removed unnecessary memory accesses
Comparing code styles
You want to compare two implementations:
x * 8
versus
x << 3
Assembly output can show whether the compiler generates the same instructions.
Understanding inlining
If a small helper function disappears from assembly at -O2, GCC may have inlined it.
Debugging low-level behavior
If a variable seems to vanish in a debugger, assembly can reveal whether it was optimized away.
Learning how C/C++ works
Assembly helps you see how:
- function calls are made
- parameters are passed
- return values are handled
- structs or classes affect generated code
Real Codebase Usage
In real projects, developers usually do not inspect assembly for every file. Instead, they generate it selectively when investigating something specific.
Common patterns
- Check one file only during optimization work:
gcc -S -O2 hot_path.c - Compare optimization levels:
gcc -S -O0 hot_path.c -o hot_path_O0.s gcc -S -O3 hot_path.c -o hot_path_O3.s - Use Intel syntax for readability:
gcc -S -masm=intel hot_path.c - Preserve source context with extra annotations:
gcc -S -g -fverbose-asm hot_path.c
How teams typically use this
- investigate why a function is slow
- verify that a branch was optimized away
- inspect generated code for embedded systems
- compare compiler versions
- check whether a
const,inline, or template change affects code generation
Related workflow tools
Developers also often combine assembly generation with:
objdump -dto disassemble compiled object files or executables- Compiler Explorer to compare output quickly
-O0, , to study optimization effects
Common Mistakes
Here are common beginner mistakes when trying to get assembly output from GCC.
Mistake 1: Using -c instead of -S
gcc -c main.c
This creates an object file like main.o, not assembly.
Use this instead:
gcc -S main.c
Mistake 2: Expecting the same assembly on every machine
Assembly depends on the target architecture.
For example:
- x86-64 output differs from ARM output
- Linux output may differ from Windows output
- optimization settings change everything
Mistake 3: Forgetting optimization flags
gcc -S main.c
This usually gives unoptimized output, which may be much more verbose than production builds.
If you want realistic optimized code, try:
gcc -S -O2 main.c
Mistake 4: Confusing assembly syntax styles
Many beginners expect Intel syntax, but GCC often emits AT&T syntax by default.
If needed, switch syntax:
gcc -S -masm=intel main.c
Comparisons
| Goal | GCC Option | What it Does |
|---|---|---|
| Generate assembly text | -S | Stops after compilation and writes assembly output |
| Generate object file | -c | Stops after assembly and writes .o file |
| Build executable | no special stop flag | Runs full pipeline through linking |
-S vs -c
| Option | Output | Human-readable? | Typical use |
|---|---|---|---|
-S |
Cheat Sheet
# C source to assembly
gcc -S file.c
# C++ source to assembly
g++ -S file.cpp
# Choose output file
gcc -S file.c -o file.s
# Optimized assembly
gcc -S -O2 file.c
# No optimization
gcc -S -O0 file.c
# Intel syntax
gcc -S -masm=intel file.c
# Extra comments in output
gcc -S -fverbose-asm file.c
# Include debug info
gcc -S -g file.c
Key rules
-Smeans stop after generating assembly.-cmeans stop after creating object code.- No stop flag means GCC usually continues through linking.
- Assembly output depends on platform, optimization, and compiler version.
- Use
g++for C++ files when you want normal C++ compilation behavior.
Common file extensions
- C source:
.c - C++ source:
.cpp,.cc,.cxx - Assembly output:
.s - Object file:
.o
Good analysis commands
FAQ
How do I generate assembly from a C file in GCC?
Use:
gcc -S file.c
This creates file.s.
How do I generate assembly from a C++ file in GCC?
Use:
g++ -S file.cpp
This generates assembly using C++ compilation rules.
What is the GCC flag for assembly output?
The main flag is -S.
Why does GCC generate a .o file instead of a .s file?
You probably used -c instead of -S. -c creates an object file.
How can I make GCC assembly easier to read?
Useful options include:
-masm=intel -fverbose-asm
These can switch syntax and add comments.
Why does my assembly look different from someone else’s?
Assembly output changes based on:
- target CPU
- operating system
- GCC version
Mini Project
Description
Create a small experiment that shows how GCC turns simple C code into assembly, and how optimization changes the result. This project helps you practice generating .s files and comparing emitted code for the same function under different compiler settings.
Goal
Generate and compare assembly output for a simple C program using both unoptimized and optimized GCC builds.
Requirements
- Write a small C program with at least two functions.
- Generate assembly output with
-O0and save it to one file. - Generate assembly output with
-O2and save it to a different file. - Use a command that writes assembly output to explicit filenames.
- Compare the two assembly files and identify at least one visible difference.
Keep learning
Related questions
Array-to-Pointer Conversion in C and C++ Explained
Learn what array-to-pointer conversion means in C and C++, how array decay works, and how it differs from a pointer to an array.
Building More Fault-Tolerant Embedded C++ Applications for Radiation-Prone ARM Systems
Learn practical C++ and compile-time techniques to reduce soft-error damage in embedded ARM systems exposed to radiation.
C Pointer to Array vs Array of Pointers: How to Read Complex Declarations
Learn the difference between pointer-to-array and array-of-pointers in C, plus a simple rule for reading complex declarations correctly.