By Doug T.


2008-09-26 00:10:21 8 Comments

How does one do this?

If I want to analyze how something is getting compiled, how would I get the emitted assembly code?

16 comments

@Himanshu Pal 2018-12-26 04:28:11

Here is a solution for C using gcc :

gcc -S program.c && gcc program.c -o output
  1. Here the first part stores the assembly output of the program in the same file name as Program but with a changed .s extension, you can open it as any normal text file.

  2. The second part here compiles your program for actual usage and generates an executable for your Program with a specified file name.

The program.c used above is the name of your program and output is the name of the executable you want to generate.

BTW It's my First post on StackOverFlow :-}

@Abhishek D K 2018-11-28 06:13:28

recently i wanted to know the assembly of each functions in a program
this is how i did it.

$ gcc main.c                      // main.c source file
$ gdb a.exe                       // gdb a.out in linux
  (gdb) disass main               // note here main is a function
                                  // similary it can be done for other functions

@PhirePhly 2008-09-26 02:51:05

This will generate the asm code with the C code + line numbers interweaved to more easily see what lines generate what code.

# create assembler code:
c++ -S -fverbose-asm -g -O2 test.cc -o test.s
# create asm interlaced with source lines:
as -alhnd test.s > test.lst

Found in Algorithms for programmers, page 3 (which is the overall 15th page of the PDF).

@Grumdrig 2013-04-05 04:51:29

(That's actually on page (numbered) 3 (which is the 15th page of the PDF))

@Grumdrig 2013-04-05 04:57:16

Sadly, as on OS X doesn't know these flags. If it did, though, you could probably one-line this using -Wa to pass options to as.

@legends2k 2013-05-06 13:49:11

g++ -g -O0 -c -fverbose-asm -Wa,-adhln test.cpp > test.lst would be the short hand version of this.

@phuclv 2014-06-07 14:28:38

You can also use either gcc -c -g -Wa,-ahl=test.s test.c or gcc -c -g -Wa,-a,-ad test.c > test.txt

@Peter Cordes 2016-07-25 00:23:24

A blog post explaining this in more detail, including the one-command version like legends and Lu'u posted. But why -O0? That's full of loads/stores that make it hard to track a value, and doesn't tell you anything about how efficient the optimized code will be.

@Ashutosh K Singh 2018-02-25 03:03:49

Output of these commnads

Here are the steps to see/print the assembly code of any C program on your Windows

console /terminal/ command prompt :

  1. Write a C program in a C code editor like codeblocks and save it with an extention .c

  2. Compile and run it.

  3. Once run successfully, go to the folder where you have installed your gcc compiler and give the

    following command to get a ' .s ' file of the ' .c' file

    C:\ gcc> gcc -S complete path of the C file ENTER

    An example command ( as in my case)

    C:\gcc> gcc -S D:\Aa_C_Certified\alternate_letters.c

    This outputs a ' .s' file of the original ' .c' file

4 . After this , type the following command

C;\gcc> cpp filename.s ENTER

Example command ( as in my case)

C;\gcc> cpp alternate_letters.s

This will print/output the entire Assembly language code of your C program.

@Antonin GAVREL 2018-01-24 15:27:12

I don't see this possibility among answers, probably because the question is from 2008, but in 2018 you can use Matt Goldbolt's online website https://godbolt.org

You can also locally git clone and run his project https://github.com/mattgodbolt/compiler-explorer

@Andrew Edgecombe 2008-09-26 00:19:43

Use the -S option to gcc (or g++).

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.

By default this will output a file helloworld.s. The output file can be still be set by using the -o option.

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

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.

@Rhys Ulerich 2013-11-03 02:13:02

While this is correct, I found the results from Cr McDonough's answer to be more useful.

@touchStone 2015-03-11 11:58:33

an addition use : objdump -M intel -S --disassemble helloworld > helloworld.dump to get the object dump in intel syntax compatible with nasm on linux.

@fiorentinoing 2015-11-11 08:06:04

If you have a single function to optimize/check, then you can give a try to online Interactive C++ Compilers i.e. godbolt

@Peter Cordes 2017-09-02 19:27:41

@touchStone: GAS .intel_syntax is not compatible with NASM. It's more like MASM (e.g. mov eax, symbol is a load, unlike in NASM where it's a mov r32, imm32 of the address), but not totally compatible with MASM either. I do highly recommend it as a nice format to read, especially if you like to write in NASM syntax though. objdump -drwC -Mintel | less or gcc foo.c -O1 -fverbose-asm -masm=intel -S -o- | less are useful. (See also How to remove “noise” from GCC/clang assembly output?). -masm=intel works with clang, too.

@Basile Starynkevitch 2017-09-21 09:02:00

Better use gcc -O -fverbose-asm -S

@Cr McDonough 2013-09-29 22:07:28

The following command line is from Christian Garbin's blog

g++ -g -O -Wa,-aslh horton_ex2_05.cpp >list.txt

I ran G++ from a DOS window on Win-XP, against a routine that contains an implicit cast

c:\gpp_code>g++ -g -O -Wa,-aslh horton_ex2_05.cpp >list.txt
horton_ex2_05.cpp: In function `int main()':
horton_ex2_05.cpp:92: warning: assignment to `int' from `double'

The output is asssembled generated code iterspersed with the original C++ code (the C++ code is shown as comments in the generated asm stream)

  16:horton_ex2_05.cpp **** using std::setw;
  17:horton_ex2_05.cpp ****
  18:horton_ex2_05.cpp **** void disp_Time_Line (void);
  19:horton_ex2_05.cpp ****
  20:horton_ex2_05.cpp **** int main(void)
  21:horton_ex2_05.cpp **** {
 164                    %ebp
 165                            subl $128,%esp
?GAS LISTING C:\DOCUME~1\CRAIGM~1\LOCALS~1\Temp\ccx52rCc.s
166 0128 55                    call ___main
167 0129 89E5          .stabn 68,0,21,LM2-_main
168 012b 81EC8000      LM2:
168      0000
169 0131 E8000000      LBB2:
169      00
170                    .stabn 68,0,25,LM3-_main
171                    LM3:
172                            movl $0,-16(%ebp)

@Jesse Chisholm 2015-08-11 21:14:59

@Paladin - Not necessarily. The OP was about getting the assembler output equivalent of the C/C++ source code, this gets the Listing, which I agree is more useful for understanding what the compiler and optimizer is doing. But it would cause the assembler itself to barf, as it is not expecting the line numbers, and compiled bytes off tot he left of the assembly instructions.

@Peter Cordes 2017-10-07 22:16:26

Use at least -O2, or whatever optimization options you actually use when building your project, if you want to see how gcc optimizes your code. (Or if you use LTO, like you should, then you have to disassemble the linker output to see what you really get.)

@METADATA 2013-06-13 08:56:37

Well, as everyone said, use -S option. If you use -save-temps option, you can also get preprocessed file(.i), assembly file(.s) and object file(*.o). (get each of them by using -E, -S, and -c.)

@mcandre 2011-10-24 06:18:37

If you're looking for LLVM assembly:

llvm-gcc -emit-llvm -S hello.c

@Grady Player 2013-02-06 23:08:09

or same command with clang

@Anonymous 2011-01-04 12:02:58

From: http://www.delorie.com/djgpp/v2faq/faq8_20.html

gcc -c -g -Wa,-a,-ad [other GCC options] foo.c > foo.lst

in alternative to PhirePhly's answer Or just use -S as everyone said.

@Pizearke 2010-12-16 02:18:14

Use "-S" as an option. It displays the assembly output in the terminal.

@Peter Cordes 2018-01-24 17:56:09

To display in the terminal, use gcc foo.c -masm=intel -fverbose-asm -O3 -S -o- |less. -S on its own creates foo.s.

@Chris Jefferson 2008-10-11 16:31:10

As mentioned before, look at the -S flag.

It's also worth looking at the '-fdump-tree' family of flags, in particular '-fdump-tree-all', which lets you see some of gcc's intermediate forms. These can often be more readable than assembler (at least to me), and let you see how optimisation passes perform.

@Dan Lenski 2008-09-26 02:06:06

As everyone has pointed out, use the -S option to GCC. I would also like to add that the results may vary (wildly!) depending on whether or not you add optimization options (-O0 for none, -O2 for agressive optimization).

On RISC architectures in particular, the compiler will often transform the code almost beyond recognition in doing optimization. It's impressive and fascinating to look at the results!

@Dark Shikari 2008-09-26 00:14:23

If what you want to see depends on the linking of the output, then objdump on the output object file/executable may also be useful in addition to the aforementioned gcc -S. Here's a very useful script by Loren Merritt that converts the default objdump syntax into the more readable nasm syntax:

#!/usr/bin/perl -w
$ptr='(BYTE|WORD|DWORD|QWORD|XMMWORD) PTR ';
$reg='(?:[er]?(?:[abcd]x|[sd]i|[sb]p)|[abcd][hl]|r1?[0-589][dwb]?|mm[0-7]|xmm1?[0-9])';
open FH, '-|', '/usr/bin/objdump', '-w', '-M', 'intel', @ARGV or die;
$prev = "";
while(<FH>){
    if(/$ptr/o) {
        s/$ptr(\[[^\[\]]+\],$reg)/$2/o or
        s/($reg,)$ptr(\[[^\[\]]+\])/$1$3/o or
        s/$ptr/lc $1/oe;
    }
    if($prev =~ /\t(repz )?ret / and
       $_ =~ /\tnop |\txchg *ax,ax$/) {
       # drop this line
    } else {
       print $prev;
       $prev = $_;
    }
}
print $prev;
close FH;

I suspect this can also be used on the output of gcc -S.

@Ruslan 2017-10-07 22:00:01

Still, this script is a dirty hack which doesn't fully convert the syntax. E.g. mov eax,ds:0x804b794 is not very NASMish. Also, sometimes it just strips useful information: movzx eax,[edx+0x1] leaves the reader to guess whether the memory operand was byte or word.

@Peter Cordes 2017-10-07 22:12:51

To disassemble in NASM syntax in the first place, use Agner Fog's objconv. You can get it to disassemble to stdout with output file = /dev/stdout, so you can pipe into less for viewing. There's also ndisasm, but it only disassembles flat binaries, and doesn't know about object files (ELF / PE).

@Jeremy Ruten 2008-09-26 00:11:32

Use the -S option:

gcc -S program.c

@Doug T. 2008-09-26 00:11:06

Use the -S switch

g++ -S main.cpp

or also with gcc

gcc -S main.c

Also see this

@Steve Jessop 2008-09-26 00:50:10

Check the FAQ: "It's also perfectly fine to ask and answer your own programming question". The point being that now StackOverflow contains the Q&A as a resource for others.

@PhirePhly 2008-09-26 03:01:34

And maybe someone else will come along and surprise you with a better answer, though mine might be a little verbose at times...

@Ciro Santilli 新疆改造中心996ICU六四事件 2013-08-24 20:05:28

There is even the answer your own question button.

Related Questions

Sponsored Content

22 Answered Questions

10 Answered Questions

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

10 Answered Questions

4 Answered Questions

[SOLVED] What does the C ??!??! operator do?

  • 2011-10-19 16:56:59
  • Peter Olson
  • 242197 View
  • 1823 Score
  • 4 Answer
  • Tags:   c operators trigraphs

35 Answered Questions

26 Answered Questions

[SOLVED] How do you set, clear, and toggle a single bit?

23 Answered Questions

[SOLVED] Compiling an application for use in highly radioactive environments

11 Answered Questions

4 Answered Questions

[SOLVED] Obfuscated C Code Contest 2006. Please explain sykes2.c

Sponsored Content