How do you get assembler output from C/C++ source in gcc?

Use the -S option to gcc (or g++), optionally with -fverbose-asm which works well at the default -O0 to attach C names to asm operands as comments. Less well at any optimization level, which you normally want to use to get asm worth looking at.

gcc -S helloworld.c

This will run the preprocessor (cpp) over helloworld.c, perform the initial compilation and then stop before the assembler is run. For useful compiler options to use in that case, see How to remove “noise” from GCC/clang assembly output? (or just look at your code on Matt Godbolt’s online Compiler Explorer which filters out directives and stuff, and has highlighting to match up source lines with asm using debug info.)

By default this will output a file helloworld.s. The output file can be still be set by using the -o option, including -o - to write to stdout for pipe into less.

gcc -S -o my_asm_output.s helloworld.c

Of course this only works if you have the original source.
An alternative if you only have the resultant object file is to use objdump, by setting the --disassemble option (or -d for the abbreviated form).

objdump -S --disassemble helloworld > helloworld.dump

-S interleaves source lines with normal disassembly output, so this option works best if debugging option is enabled for the object file (-g at compilation time) and the file hasn’t been stripped.

Running file helloworld will give you some indication as to the level of detail that you will get by using objdump.

Other useful objdump options include -rwC (to show symbol relocations, disable line-wrapping of long machine code, and demangle C++ names). And if you don’t like AT&T syntax for x86, -Mintel. See the man page.

So for example, objdump -drwC -Mintel -S foo.o | less.
-r is very important with a .o that only has 00 00 00 00 placeholders for symbol references, as opposed to a linked executable.

Leave a Comment