Wie erhalten Sie eine Assembler-Ausgabe aus der C/C++-Quelle in gcc?

Lesezeit: 8 Minuten

Wie erhalten Sie eine Assembler Ausgabe aus der CC Quelle in gcc
Doug T.

Wie macht man das?

Wenn ich analysieren möchte, wie etwas kompiliert wird, wie bekomme ich den ausgegebenen Assemblercode?

  • Für Tipps bzgl macht die asm-Ausgabe für Menschen lesbarsiehe auch: Wie entferne ich „Rauschen“ aus der GCC/Clang-Assembly-Ausgabe?

    – Peter Cordes

    26. Juli 2016 um 4:30 Uhr


Wie erhalten Sie eine Assembler Ausgabe aus der CC Quelle in gcc
Andrew Edgecombe

Verwenden Sie die -S Option zu 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 gestoppt, bevor der Assembler ausgeführt wird.

Standardmäßig wird eine Datei ausgegeben helloworld.s. Die Ausgabedatei kann noch über die eingestellt werden -o Möglichkeit.

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 zu verwenden objdumpindem Sie die --disassemble Möglichkeit (bzw -d für die Kurzform).

objdump -S --disassemble helloworld > helloworld.dump

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

Laufen file helloworld gibt Ihnen einen Hinweis auf den Detaillierungsgrad, den Sie durch die Verwendung von objdump erhalten.

  • Verwenden Sie zusätzlich: objdump -M intel -S –disassemble helloworld > helloworld.dump, um den Objekt-Dump in Intel-Syntax zu erhalten, der mit Nasm unter Linux kompatibel ist.

    – Berührungsstein

    11. März 2015 um 11:58 Uhr

  • Wenn Sie eine einzelne Funktion optimieren/überprüfen müssen, können Sie interaktive C++-Compiler online ausprobieren, z Gottriegel

    – Florenz

    11. November 2015 um 8:06 Uhr

  • @touchStone: GAS .intel_syntax ist nicht Kompatibel mit NASM. Es ist eher wie MASM (zB mov eax, symbol ist eine Last, anders als in NASM, wo es a ist mov r32, imm32 der Adresse), aber auch nicht vollständig kompatibel mit MASM. Ich empfehle es sehr als nettes Format zum Lesen, besonders wenn Sie gerne in NASM-Syntax schreiben. objdump -drwC -Mintel | less oder gcc foo.c -O1 -fverbose-asm -masm=intel -S -o- | less sind nützlich. (Siehe auch Wie entferne ich „Rauschen“ aus der GCC/Clang-Assembly-Ausgabe?). -masm=intel funktioniert auch mit clang.

    – Peter Cordes

    2. September 2017 um 19:27 Uhr


  • Besser verwenden gcc -O -fverbose-asm -S

    – Basile Starynkevitch

    21. September 2017 um 9:02 Uhr

1647159009 185 Wie erhalten Sie eine Assembler Ausgabe aus der CC Quelle in gcc
PhirePhly

Dadurch wird Assemblercode mit verwobenem C-Code + Zeilennummern generiert, um leichter zu erkennen, welche Zeilen welchen Code generieren:

# 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 ProgrammiererSeite 3 (das ist die insgesamt 15. Seite des PDF).

  • Leider, as unter OS X kennt diese Flags nicht. Wenn dies jedoch der Fall wäre, könnten Sie dies wahrscheinlich mit einer Zeile eingrenzen -Wa Optionen zu übergeben as.

    – Grumdrig

    5. April 2013 um 4:57 Uhr

  • g++ -g -O0 -c -fverbose-asm -Wa,-adhln test.cpp > test.lst wäre die Kurzfassung davon.

    – legends2k

    6. Mai 2013 um 13:49 Uhr

  • Sie können auch beides verwenden gcc -c -g -Wa,-ahl=test.s test.c oder gcc -c -g -Wa,-a,-ad test.c > test.txt

    – phuklv

    7. Juni 2014 um 14:28 Uhr

  • EIN Blogeintrag Erklären Sie dies ausführlicher, einschließlich der Ein-Befehl-Version, wie Legends und Lu’u gepostet haben. Aber warum -O0? Das ist voll von Ladevorgängen/Speichern, die es schwierig machen, einen Wert zu verfolgen, und sagt Ihnen nichts darüber aus, wie effizient der optimierte Code sein wird.

    – Peter Cordes

    25. Juli 2016 um 0:23 Uhr


1647159010 478 Wie erhalten Sie eine Assembler Ausgabe aus der CC Quelle in gcc
Cr McDonough

Die folgende Befehlszeile stammt von Blog von Christian Garbin

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

Ich habe G++ von einem DOS-Fenster unter Win-XP gegen eine Routine ausgeführt, die eine implizite Umwandlung 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 Kommentare 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)

  • @Paladin – Nicht unbedingt. Beim OP ging es darum, das Assembler-Ausgabeäquivalent des C/C++-Quellcodes zu erhalten, dies erhält das Listing, das meines Erachtens nützlicher ist, um zu verstehen, was der Compiler und der Optimierer tun. Aber es würde den Assembler selbst zum Kotzen bringen, da er die Zeilennummern nicht erwartet, und kompilierte Bytes links von den Assembleranweisungen.

    – Jesse Chisholm

    11. August 2015 um 21:14 Uhr

  • Benutze mindestens -O2, oder welche Optimierungsoptionen Sie auch immer beim Erstellen Ihres Projekts verwenden, wenn Sie sehen möchten, wie gcc Ihren Code optimiert. (Oder wenn Sie LTO verwenden, wie Sie es sollten, dann müssen Sie die Linker-Ausgabe zerlegen, um zu sehen, was Sie wirklich bekommen.)

    – Peter Cordes

    7. Oktober 2017 um 22:16 Uhr

  • @PeterCordes es gibt einen einfacheren Weg, siehe diese Frage

    – jugr

    29. Dezember 2021 um 8:05 Uhr


Verwenden Sie den Schalter -S

g++ -S main.cpp

oder auch mit gcc

gcc -S main.c

Siehe auch Das

Wie erhalten Sie eine Assembler Ausgabe aus der CC Quelle in gcc
Ciro Santilli Путлер Капут 六四事

-save-temps

Dies wurde unter https://stackoverflow.com/a/17083009/895245 erwähnt, aber lassen Sie mich es weiter veranschaulichen.

Der große Vorteil dieser Option gegenüber -S ist, dass es sehr einfach zu jedem Build-Skript hinzugefügt werden kann, ohne viel in den Build selbst einzugreifen.

Wenn Sie das tun:

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

Haupt c

#define INC 1

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

und jetzt neben der normalen Ausgabe main.oenthält das aktuelle Arbeitsverzeichnis außerdem die folgenden Dateien:

  • main.i ist ein Bonus und enthält die vorverarbeitete 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 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
    

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

 -save-temps=obj

Dadurch werden die Zwischendateien im selben Verzeichnis wie die gespeichert -o Objektausgabe anstelle des aktuellen Arbeitsverzeichnisses, wodurch potenzielle Basisnamenkonflikte vermieden werden.

Eine weitere coole Sache an dieser Option ist, wenn Sie hinzufügen -v:

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

Es zeigt tatsächlich die expliziten Dateien, die anstelle von hässlichen temporären Dateien verwendet werden /tmpso ist es einfach, genau zu wissen, was vor sich geht, einschließlich der Vorverarbeitungs- / Kompilierungs- / Montageschritte:

/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 in Ubuntu 19.04 amd64, GCC 8.3.0.

CMake vordefinierte Ziele

CMake stellt automatisch Ziele für die vorverarbeitete Datei bereit:

make help

zeigt uns, was wir können:

make main.s

und dieses 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 kann die Datei unter eingesehen werden CMakeFiles/main.dir/main.c.s

Getestet auf cmake 3.16.1.

1647159011 737 Wie erhalten Sie eine Assembler Ausgabe aus der CC Quelle in gcc
Dunkle Shikari

Wenn das, was Sie sehen möchten, von der Verknüpfung der Ausgabe abhängt, kann zusätzlich zu dem oben genannten gcc -S auch objdump in der Ausgabeobjektdatei / ausführbaren Datei nützlich sein. Hier ist ein sehr nützliches Skript von Loren Merritt, das die Standard-objdump-Syntax in die besser lesbare Nasm-Syntax konvertiert:

#!/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;

Ich vermute, dass dies auch für die Ausgabe von gcc -S verwendet werden kann.

1647159011 215 Wie erhalten Sie eine Assembler Ausgabe aus der CC Quelle in gcc
METADATEN

Nun, wie alle sagten, verwenden Sie die Option -S. Wenn Sie die Option -save-temps verwenden, können Sie auch eine vorverarbeitete Datei (.i), Assembly-Datei (.s) und Objektdatei (*.o). (holen Sie sich jeden von ihnen mit -E, -S und -c.)

996570cookie-checkWie erhalten Sie eine Assembler-Ausgabe aus der C/C++-Quelle in gcc?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy