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

How does one do this?

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

This question is related to c++ c debugging gcc assembly

The answer is


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.


This will generate assembly code with the C code + line numbers interweaved, to more easily see which lines generate what code:

# create assembler code:
g++ -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).


-save-temps

This was mentioned at https://stackoverflow.com/a/17083009/895245 but let me further exemplify it.

The big advantage of this option over -S is that it is very easy to add it to any build script, without interfering much in the build itself.

When you do:

gcc -save-temps -c -o main.o main.c

main.c

#define INC 1

int myfunc(int i) {
    return i + INC;
}

and now, besides the normal output main.o, the current working directory also contains the following files:

  • main.i is a bonus and contains the preprossessed file:

    # 1 "main.c"
    # 1 "<built-in>"
    # 1 "<command-line>"
    # 31 "<command-line>"
    # 1 "/usr/include/stdc-predef.h" 1 3 4
    # 32 "<command-line>" 2
    # 1 "main.c"
    
    
    int myfunc(int i) {
        return i + 1;
    }
    
  • main.s contains the desired generated assembly:

        .file   "main.c"
        .text
        .globl  myfunc
        .type   myfunc, @function
    myfunc:
    .LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movl    %edi, -4(%rbp)
        movl    -4(%rbp), %eax
        addl    $1, %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
    .LFE0:
        .size   myfunc, .-myfunc
        .ident  "GCC: (Ubuntu 8.3.0-6ubuntu1) 8.3.0"
        .section    .note.GNU-stack,"",@progbits
    

If you want to do it for a large number of files, consider using instead:

 -save-temps=obj

which saves the intermediate files to the same directory as the -o object output instead of the current working directory, thus avoiding potential basename conflicts.

Another cool thing about this option is if you add -v:

gcc -save-temps -c -o main.o -v main.c

it actually shows the explicit files being used instead of ugly temporaries under /tmp, so it is easy to know exactly what is going on, which includes the preprocessing / compilation / assembly steps:

/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu main.c -mtune=generic -march=x86-64 -fpch-preprocess -fstack-protector-strong -Wformat -Wformat-security -o main.i
/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -fpreprocessed main.i -quiet -dumpbase main.c -mtune=generic -march=x86-64 -auxbase-strip main.o -version -fstack-protector-strong -Wformat -Wformat-security -o main.s
as -v --64 -o main.o main.s

Tested in Ubuntu 19.04 amd64, GCC 8.3.0.

CMake predefined targets

CMake automatically provides a targets for the preprocessed file:

make help

shows us that we can do:

make main.s

and that target runs:

Compiling C source to assembly CMakeFiles/main.dir/main.c.s
/usr/bin/cc    -S /home/ciro/hello/main.c -o CMakeFiles/main.dir/main.c.s

so the file can be seen at CMakeFiles/main.dir/main.c.s

Tested on cmake 3.16.1.


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


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.


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.


If you're looking for LLVM assembly:

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

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!


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

Use the -S option:

gcc -S program.c

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


Use the -S switch

g++ -S main.cpp

or also with gcc

gcc -S main.c

Also see this


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.


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 :-}


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.)


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)

Examples related to c++

Method Call Chaining; returning a pointer vs a reference? How can I tell if an algorithm is efficient? Difference between opening a file in binary vs text How can compare-and-swap be used for a wait-free mutual exclusion for any shared data structure? Install Qt on Ubuntu #include errors detected in vscode Cannot open include file: 'stdio.h' - Visual Studio Community 2017 - C++ Error How to fix the error "Windows SDK version 8.1" was not found? Visual Studio 2017 errors on standard headers How do I check if a Key is pressed on C++

Examples related to c

conflicting types for 'outchar' Can't compile C program on a Mac after upgrade to Mojave Program to find largest and second largest number in array Prime numbers between 1 to 100 in C Programming Language In c, in bool, true == 1 and false == 0? How I can print to stderr in C? Visual Studio Code includePath "error: assignment to expression with array type error" when I assign a struct field (C) Compiling an application for use in highly radioactive environments How can you print multiple variables inside a string using printf?

Examples related to debugging

How do I enable logging for Spring Security? How to run or debug php on Visual Studio Code (VSCode) How do you debug React Native? How do I debug "Error: spawn ENOENT" on node.js? How can I inspect the file system of a failed `docker build`? Swift: print() vs println() vs NSLog() JavaScript console.log causes error: "Synchronous XMLHttpRequest on the main thread is deprecated..." How to debug Spring Boot application with Eclipse? Unfortunately MyApp has stopped. How can I solve this? 500 internal server error, how to debug

Examples related to gcc

Can't compile C program on a Mac after upgrade to Mojave Compiling an application for use in highly radioactive environments Make Error 127 when running trying to compile code How to Install gcc 5.3 with yum on CentOS 7.2? How does one set up the Visual Studio Code compiler/debugger to GCC? How do I set up CLion to compile and run? CMake error at CMakeLists.txt:30 (project): No CMAKE_C_COMPILER could be found How to printf a 64-bit integer as hex? Differences between arm64 and aarch64 Fatal error: iostream: No such file or directory in compiling C program using GCC

Examples related to assembly

Why does C++ code for testing the Collatz conjecture run faster than hand-written assembly? While, Do While, For loops in Assembly Language (emu8086) Replacing a 32-bit loop counter with 64-bit introduces crazy performance deviations with _mm_popcnt_u64 on Intel CPUs How to run a program without an operating system? Difference between "move" and "li" in MIPS assembly language Carry Flag, Auxiliary Flag and Overflow Flag in Assembly How do AX, AH, AL map onto EAX? JNZ & CMP Assembly Instructions Difference between JE/JNE and JZ/JNZ The point of test %eax %eax