📅 2019-Dec-30 ⬩ ✍️ Ashwin Nanjappa ⬩ 🏷️ assembly, gcc ⬩ 📚 Archive
When we use GCC to compile C or C++ code, it directly generates the final object or executable file. For example, this command generates an a.out
executable:
$ g++ foobar.cpp
I find it useful to generate assembly code to understand what the compiler is doing to my C++ code. To generate assembly code we essentially request GCC to stop before the assembly stage of compilation and dump what it has generated from the compiler backend.
To generate assembly code:
$ g++ -S foobar.cpp
This writes the assembly code to a foobar.s
file. For x86 and x64 assembly code, the AT&T syntax is used by default.
To generate assembly code in Intel syntax:
$ g++ -S -masm=intel foobar.cpp
The assembly code generated by the above -S
option does not have any annotations indicating which lines of the C++ code correspond to which assembly instructions.
To get assembly code with annotations of the C++ source code:
$ gcc -S -fverbose-asm foobar.cpp
This option adds two types of extra commentary. First, every statement of the C++ code appears in the assembly code. This makes it easy to identify which assembly code lines correspond to every C++ source line. Note that function definition lines from C++ do not appear though, but I can usually identify them by looking at their mangled label name. Second, every assembly code line that uses registers has a comment to its right indicating which variable from the C++ code is being read or written. I find this information takes off a huge burden when reading assembly code.
To get elaborate commentary in the assembly code:
$ gcc -g -Wa,-adhln foobar.cpp > foobar.s
The -adhln
options are passed to the assembler since we prefixed it with -Wa
. The -adhln
options essentially ask the assembler to enable assembly code listings -a
, omit debugging directives -d
, include C++ source code -h
, include assembly -l
and omit other stuff -n
.
The above option provides the most pleasing annotations for assembly code. Unlike the -fverbose-asm
option, this one includes all the C++ source lines including function definition lines. However, this invocation does not have commentary beside each assembly line indicating which C++ variable is being held in registers in that line.
Thankfully, all these options can be combined to generate the most detailed annotated assembly code:
$ gcc -g -Wa,-adhln -fverbose-asm foobar.cpp > foobar.s
Tried with: GCC 7.4.0 and Ubuntu 18.04