By James


2009-08-17 19:22:17 8 Comments

I was wondering how to use GCC on my C source file to dump a mnemonic version of the machine code so I could see what my code was being compiled into. You can do this with Java but I haven't been able to find a way with GCC.

I am trying to re-write a C method in assembly and seeing how GCC does it would be a big help.

9 comments

@Basile Starynkevitch 2011-11-01 22:14:11

Did you try gcc -S -fverbose-asm -O source.c then look into the generated source.s assembler file ?

The generated assembler code goes into source.s (you could override that with -o assembler-filename ); the -fverbose-asm option asks the compiler to emit some assembler comments "explaining" the generated assembler code. The -O option asks the compiler to optimize a bit (it could optimize more with -O2 or -O3).

If you want to understand what gcc is doing try passing -fdump-tree-all but be cautious: you'll get hundreds of dump files.

BTW, GCC is extensible thru plugins or with MELT (a high level domain specific language to extend GCC; which I abandoned in 2017)

@ecerulm 2015-07-02 08:41:22

maybe mention that the output will be in source.s, since a lot of people would expect a printout on the console.

@Peter Cordes 2016-01-30 23:06:00

@ecerulm: -S -o- dumps to stdout. -masm=intel is helpful if you want to use NASM/YASM syntax. (but it uses qword ptr [mem], rather than just qword, so it's more like Intel/MASM than NASM/YASM). gcc.godbolt.org does a nice job of tidying up the dump: optionally stripping comment-only lines, unused labels, and assembler directives.

@Peter Cordes 2016-01-31 13:41:10

Forgot to mention: If you're looking for "similar to the source but without the noise of store/reload after every source line", then -Og is even better than -O1. It means "optimize for debugging" and makes asm without too many tricky / hard-to-follow optimizations that does everything the source says. It's been available since gcc4.8, but clang 3.7 still doesn't have it. IDK if they decided against it or what.

@Bastien Léonard 2009-08-17 19:28:06

If you compile with debug symbols, you can use objdump to produce a more readable disassembly.

>objdump --help
[...]
-S, --source             Intermix source code with disassembly
-l, --line-numbers       Include line numbers and filenames in output

objdump -drwC -Mintel is nice:

  • -r shows symbol names on relocations (so you'd see puts in the call instruction below)
  • -R shows dynamic-linking relocations / symbol names (useful on shared libraries)
  • -C demangles C++ symbol names
  • -w is "wide" mode: it doesn't line-wrap the machine-code bytes
  • -Mintel: use GAS/binutils MASM-like .intel_syntax noprefix syntax instead of AT&T
  • -S: interleave source lines with disassembly.

You could put something like alias disas="objdump -drwCS -Mintel" in your ~/.bashrc


Example:

> gcc -g -c test.c
> objdump -d -M intel -S test.o

test.o:     file format elf32-i386


Disassembly of section .text:

00000000 <main>:
#include <stdio.h>

int main(void)
{
   0:   55                      push   ebp
   1:   89 e5                   mov    ebp,esp
   3:   83 e4 f0                and    esp,0xfffffff0
   6:   83 ec 10                sub    esp,0x10
    puts("test");
   9:   c7 04 24 00 00 00 00    mov    DWORD PTR [esp],0x0
  10:   e8 fc ff ff ff          call   11 <main+0x11>

    return 0;
  15:   b8 00 00 00 00          mov    eax,0x0
}
  1a:   c9                      leave  
  1b:   c3                      ret

@James 2009-08-17 19:39:46

Is there a switch to grab only the Intel instructions?

@toto 2009-08-18 04:01:02

All of these are Intel instructions since they run on Intel processors :D.

@Amok 2009-10-09 21:56:36

@toto I think he means Intel syntax instead of AT&T syntax

@Marc Butler 2010-09-08 16:45:04

It is possible to forgo the intermediate object file with the by using the switch sequence -Wa,-adhln -g to gcc. This assumes that the assembler is gas and this may not always be the case.

@fuz 2015-09-26 15:42:23

@James Yes, supply -Mintel.

@transang 2015-12-05 14:14:39

Use otool -tV for Mac user :)

@YungGun 2019-09-14 21:26:43

Doesn't work on Mac.

@amaterasu 2009-08-18 07:10:17

Using the -S switch to GCC on x86 based systems produces a dump of AT&T syntax, by default, which can be specified with the -masm=att switch, like so:

gcc -S -masm=att code.c

Whereas if you'd like to produce a dump in Intel syntax, you could use the -masm=intel switch, like so:

gcc -S -masm=intel code.c

(Both produce dumps of code.c into their various syntax, into the file code.s respectively)

In order to produce similar effects with objdump, you'd want to use the --disassembler-options= intel/att switch, an example (with code dumps to illustrate the differences in syntax):

 $ objdump -d --disassembler-options=att code.c
 080483c4 <main>:
 80483c4:   8d 4c 24 04             lea    0x4(%esp),%ecx
 80483c8:   83 e4 f0                and    $0xfffffff0,%esp
 80483cb:   ff 71 fc                pushl  -0x4(%ecx)
 80483ce:   55                      push   %ebp
 80483cf:   89 e5                   mov    %esp,%ebp
 80483d1:   51                      push   %ecx
 80483d2:   83 ec 04                sub    $0x4,%esp
 80483d5:   c7 04 24 b0 84 04 08    movl   $0x80484b0,(%esp)
 80483dc:   e8 13 ff ff ff          call   80482f4 <[email protected]>
 80483e1:   b8 00 00 00 00          mov    $0x0,%eax
 80483e6:   83 c4 04                add    $0x4,%esp 
 80483e9:   59                      pop    %ecx
 80483ea:   5d                      pop    %ebp
 80483eb:   8d 61 fc                lea    -0x4(%ecx),%esp
 80483ee:   c3                      ret
 80483ef:   90                      nop

and

$ objdump -d --disassembler-options=intel code.c
 080483c4 <main>:
 80483c4:   8d 4c 24 04             lea    ecx,[esp+0x4]
 80483c8:   83 e4 f0                and    esp,0xfffffff0
 80483cb:   ff 71 fc                push   DWORD PTR [ecx-0x4]
 80483ce:   55                      push   ebp
 80483cf:   89 e5                   mov    ebp,esp
 80483d1:   51                      push   ecx
 80483d2:   83 ec 04                sub    esp,0x4
 80483d5:   c7 04 24 b0 84 04 08    mov    DWORD PTR [esp],0x80484b0
 80483dc:   e8 13 ff ff ff          call   80482f4 <[email protected]>
 80483e1:   b8 00 00 00 00          mov    eax,0x0
 80483e6:   83 c4 04                add    esp,0x4
 80483e9:   59                      pop    ecx
 80483ea:   5d                      pop    ebp
 80483eb:   8d 61 fc                lea    esp,[ecx-0x4]
 80483ee:   c3                      ret    
 80483ef:   90                      nop

@L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ 2009-11-22 04:03:59

What the... gcc -S -masm=intel test.c didn't exactly work for me, I got some crossbreed of Intel and AT&T syntax like this: mov %rax, QWORD PTR -24[%rbp], instead of this: movq -24(%rbp), %rax.

@underscore_d 2015-12-20 21:49:11

Nice tip. It should be noted this also works when performing parallel output of .o and ASM files, i.e. via -Wa,-ahls -o yourfile.o yourfile.cpp>yourfile.asm

@Eric Wang 2016-07-05 04:57:42

Could use -M option, it's the same as --disassembler-options but much shorter, e.g objdump -d -M intel a.out | less -N

@Andrew Keeton 2009-08-17 19:24:31

Use the -S (note: capital S) switch to GCC, and it will emit the assembly code to a file with a .s extension. For example, the following command:

gcc -O2 -S foo.c

will leave the generated assembly code on the file foo.s.

Ripped straight from http://www.delorie.com/djgpp/v2faq/faq8_20.html (but removing erroneous -c)

@Adam Rosenfield 2009-08-17 19:28:23

You shouldn't mix -c and -S, only use one of them. In this case, one is overriding the other, probably depending on the order in which they're used.

@Tony 2014-08-05 11:55:36

@AdamRosenfield Any reference about 'shouldn't mix -c and -S'? If it is true, we may should remind the author and edit it.

@Nate Eldredge 2016-04-10 00:32:23

@Tony: gcc.gnu.org/onlinedocs/gcc/Overall-Options.html#Overall-Opti‌​ons "You can use ... one of the options -c, -S, or -E to say where gcc is to stop."

@Peter Cordes 2018-06-02 01:21:55

If you want all the intermediate outputs, use gcc -march=native -O3 -save-temps. You can still use -c to stop at object-file creation without trying to link, or whatever.

@DAG 2016-03-30 06:00:56

I haven't given a shot to gcc, but in case of g++. The command below works for me. -g for debug build and -Wa,-adhln is passed to assembler for listing with source code

g++ -g -Wa,-adhln src.cpp

@Shafik Yaghmour 2014-09-11 07:47:09

godbolt is a very useful tool, they list only has C++ compilers but you can use -x c flag in order to get it treat the code as C. It will then generate an assembly listing for your code side by side and you can use the Colourise option to generate colored bars to visually indicate which source code maps to the generated assembly. For example the following code:

#include <stdio.h>

void func()
{
  printf( "hello world\n" ) ;
}

using the following command line:

-x c -std=c99 -O3

and Colourise would generate the following:

enter image description here

@Z boson 2017-02-22 08:01:01

It would be nice to know how godbolt filters work: .LC0, .text, //, and Intel. Intel is easy -masm=intel but what about the rest?

@Z boson 2017-02-22 08:02:22

I guess it is explained here stackoverflow.com/a/38552509/2542702

@Ludwig Schreier 2017-09-21 13:06:57

Complementary online disassembler: onlinedisassembler.com/odaweb

@phuclv 2019-04-27 09:34:18

godbolt do support C (along with a ton of other languages like Rust, D, Pascal...). It's just that there are much fewer C compilers, so it's still better to use C++ compilers with -x c

@kmm 2009-08-17 20:23:12

I would like to add to these answers that if you give gcc the flag -fverbose-asm, the assembler it emits will be a lot clearer to read.

@Vishal Sagar 2009-08-19 08:41:49

You can use gdb for this like objdump.

This excerpt is taken from http://sources.redhat.com/gdb/current/onlinedocs/gdb_9.html#SEC64


Here is an example showing mixed source+assembly for Intel x86:

  (gdb) disas /m main
Dump of assembler code for function main:
5       {
0x08048330 :    push   %ebp
0x08048331 :    mov    %esp,%ebp
0x08048333 :    sub    $0x8,%esp
0x08048336 :    and    $0xfffffff0,%esp
0x08048339 :    sub    $0x10,%esp

6         printf ("Hello.\n");
0x0804833c :   movl   $0x8048440,(%esp)
0x08048343 :   call   0x8048284 

7         return 0;
8       }
0x08048348 :   mov    $0x0,%eax
0x0804834d :   leave
0x0804834e :   ret

End of assembler dump.

@Ruslan 2018-05-30 16:26:23

And to switch GDB's disassembler to Intel syntax, use set disassembly-flavor intel command.

@codymanix 2009-08-17 19:24:42

Use the -S (note: capital S) switch to GCC, and it will emit the assembly code to a file with a .s extension. For example, the following command:

gcc -O2 -S -c foo.c

Related Questions

Sponsored Content

10 Answered Questions

[SOLVED] Improve INSERT-per-second performance of SQLite?

6 Answered Questions

12 Answered Questions

4 Answered Questions

1 Answered Questions

[SOLVED] How are GCC and g++ bootstrapped?

4 Answered Questions

[SOLVED] How do I achieve the theoretical maximum of 4 FLOPs per cycle?

10 Answered Questions

2 Answered Questions

2 Answered Questions

32 Answered Questions

[SOLVED] Why aren't programs written in Assembly more often?

Sponsored Content