529 Stimmen

Wie erhalten Sie Assembler-Ausgabe von C/C++-Quellcode in gcc?

Wie kann man das tun?

Wenn ich analysieren möchte, wie etwas kompiliert wird, wie erhalte ich dann den emittierten Assemblercode?

590voto

Andrew Edgecombe Punkte 37795

Verwenden Sie die -S Option für gcc (oder g++).

gcc -S helloworld.c

Dadurch wird der Präprozessor (cpp) über helloworld.c ausgeführt, die anfängliche Kompilierung durchgeführt und dann angehalten, bevor der Assembler ausgeführt wird.

Standardmäßig wird dabei eine Datei ausgegeben helloworld.s . Die Ausgabedatei kann immer noch mit Hilfe der Option -o Option.

gcc -S -o my_asm_output.s helloworld.c

Dies funktioniert natürlich nur, wenn Sie die Originalquelle haben. Eine Alternative, wenn Sie nur die resultierende Objektdatei haben, ist die Verwendung von objdump durch die Einstellung der --disassemble Option (oder -d für die abgekürzte Form).

objdump -S --disassemble helloworld > helloworld.dump

Diese Option funktioniert am besten, wenn die Debugging-Option für die Objektdatei aktiviert ist ( -g zum Zeitpunkt der Kompilierung) und die Datei wurde nicht entfernt.

Laufen file helloworld gibt Ihnen einen Anhaltspunkt für die Detailgenauigkeit, die Sie durch die Verwendung von objdump erhalten.

211voto

PhirePhly Punkte 2756

Dadurch wird Assembler-Code mit dem C-Code und den Zeilennummern verwoben, damit man leichter erkennen kann, welche Zeilen welchen Code erzeugen:

# 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

Gefunden in Algorithmen für Programmierer Seite 3 (die insgesamt 15. Seite der PDF-Datei).

54voto

Cr McDonough Punkte 701

Die folgende Befehlszeile stammt aus Christian Garbin's Blog

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

Ich habe G++ von einem DOS-Fenster auf Win-XP gegen eine Routine laufen lassen, die einen impliziten Cast enthält

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'

Die Ausgabe ist zusammengesetzter generierter Code, der mit dem ursprünglichen C++-Code durchsetzt ist (der C++-Code wird als Kommentar im generierten asm-Stream angezeigt)

  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)

38voto

Doug T. Punkte 61739

Verwenden Sie den Schalter -S

g++ -S main.cpp

oder auch mit gcc

gcc -S main.c

Siehe auch ce

34voto

-save-temps

Dies wurde erwähnt unter https://stackoverflow.com/a/17083009/895245 aber lassen Sie mich das noch einmal verdeutlichen.

Der große Vorteil dieser Option gegenüber -S ist, dass es sehr einfach ist, es zu jedem Build-Skript hinzuzufügen, ohne den Build selbst wesentlich zu beeinträchtigen.

Wenn Sie das tun:

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

main.c

#define INC 1

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

und jetzt, neben der normalen Ausgabe main.o enthält das aktuelle Arbeitsverzeichnis auch die folgenden Dateien:

  • main.i ist ein Bonus und enthält die Preprossessed-Datei:

    # 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 enthält die gewünschte generierte Baugruppe:

        .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

Wenn Sie dies für eine große Anzahl von Dateien tun möchten, sollten Sie stattdessen die Option

 -save-temps=obj

die die Zwischendateien in demselben Verzeichnis wie die -o Objektausgabe anstelle des aktuellen Arbeitsverzeichnisses, wodurch potenzielle Dateinamenkonflikte vermieden werden.

Ein weiterer Vorteil dieser Option ist, dass Sie -v :

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

zeigt es tatsächlich die expliziten Dateien an, die verwendet werden, anstatt hässliche temporäre Dateien unter /tmp Damit ist es einfach, genau zu wissen, was vor sich geht, einschließlich der Vorverarbeitungs-, Kompilierungs- und Assemblierungsschritte:

/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

Getestet unter Ubuntu 19.04 amd64, GCC 8.3.0.

CMake vordefinierte Ziele

CMake stellt automatisch ein Ziel für die vorverarbeitete Datei bereit:

make help

zeigt uns, was wir tun können:

make main.s

und das Ziel läuft:

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 dass die Datei zu sehen ist unter CMakeFiles/main.dir/main.c.s

Getestet mit cmake 3.16.1.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X