Frage

Wie kann man das tun?

Wenn ich analysieren möchten, wie ist etwas kompiliert bekommen, wie würde ich das ausgegebene Assembly-Code?

War es hilfreich?

Lösung

Mit der -S Option gcc (oder g ++).

gcc -S helloworld.c

Damit wird den Präprozessor (CPP) über HelloWorld.c laufen, die erste Kompilierung durchführt und dann stoppen, bevor der Assembler ausgeführt wird.

In der Standardeinstellung dieses Willen Ausgabe einer Datei helloworld.s. Die Ausgabedatei kann immer noch mit Hilfe der -o Option eingestellt werden werden.

gcc -S -o my_asm_output.s helloworld.c

Natürlich funktioniert dies nur, wenn Sie die ursprüngliche Quelle haben. Eine Alternative, wenn Sie nur die resultierende Objektdatei haben, ist objdump zu verwenden, indem die --disassemble Option Einstellung (oder -d für die Kurzform).

objdump -S --disassemble helloworld > helloworld.dump

Diese Option funktioniert am besten, wenn die Option Debuggen für die Objektdatei (-g bei der Kompilierung) aktiviert ist und die Datei entfernt worden ist.

Beim Laufen file helloworld gibt Ihnen einige Hinweise auf die Detailebene, die Sie mit objdump bekommen.

Andere Tipps

Dies wird den asm-Code mit den leichten verwebt C-Code + Zeilennummern erzeugen, um zu sehen, welche Zeilen erzeugen, was 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

Algorithmen gefunden für Programmierer , Seite 3 (die die Gesamt 15. ist Seite die PDF).

Die folgende Befehlszeile ist von Christian Garbin ist Blog

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

Ich lief G ++ von einem DOS-Fenster auf Win-XP, gegen eine Routine, 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'

Der Ausgang wird asssembled erzeugte Code mit dem ursprünglichen iterspersed C ++ Code (der C ++ Code wird als Kommentare in dem erzeugten Strom ASM gezeigt)

  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)

Mit dem Schalter ES

g++ -S main.cpp

oder auch mit gcc

gcc -S main.c

Auch dieser

Wenn das, was Sie auf die Verknüpfung des Ausgangs hängt zu sehen, dann objdump auf der Ausgabeobjektdatei / ausführbare kann auch zusätzlich zu dem oben erwähnten gcc -S nützlich sein. Hier ist ein sehr nützliches Skript von Loren Merritt, den die Standard objdump Syntax in die lesbaren 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, dies kann auch auf der Ausgabe von gcc -S verwendet werden.

Nun, wie alle gesagt, verwenden Sie Option -S. Wenn Sie -save-temps Option verwenden, können Sie auch vorverarbeiteten Datei erhalten ( .i), Baugruppendatei ( · s) und Objektdatei (*. O). (Erhalten Sie jede von ihnen durch die Verwendung -E, -S und -C.)

Wie jeder bemerkt hat, verwenden Sie die -S Option GCC. Ich möchte auch hinzufügen, dass die Ergebnisse können variieren (wild!), Je nachdem, ob oder nicht Sie Optimierungsoptionen (-O0 für keine, -O2 für agressive Optimierung) hinzuzufügen.

Auf RISC-Architekturen insbesondere wird die Compiler-Transformation oft den Code fast bis zur Unkenntlichkeit in der Optimierung zu tun. Es ist beeindruckend und faszinierend, die Ergebnisse zu sehen!

Wie bereits erwähnt, sehen Sie die -S-Flagge.

Es ist auch ein Blick wert die ‚-fdump Baum‘ Familie von Fahnen, insbesondere ‚-fdump-Baum-all‘, die einige von gcc Zwischenformen sehen kann. Diese können oft besser lesbar als Assembler (zumindest für mich), und lassen Sie sehen, wie Optimierungsläufe durchführen.

Mit der Option ES:

gcc -S program.c

Wenn Sie suchen LLVM Montage:

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

Ich sehe diese Möglichkeit nicht unter Antworten, wahrscheinlich, weil die Frage aus dem Jahr 2008, aber im Jahr 2018 können Sie Matt Goldbolt Online-Website verwenden https://godbolt.org

Sie können auch lokal git clone und führen sein Projekt https://github.com/mattgodbolt/compiler- explorer

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

gcc -c -g -Wa, -a, -ad [andere GCC-Optionen] foo.c> foo.lst

Als Alternative zu dem PhirePhly Antwort Oder nur ES verwenden, wie jeder gesagt hat.

Hier sind die Schritte, um zu sehen / den Assembler-Code von jedem C-Programm auf Ihrem Windows drucken

Konsole / Terminal / Eingabeaufforderung ein:

  1. ein C-Programm in einem C-Code-Editor wie Codeblocks schreiben und es mit einer Erweiterung .c speichern

  2. Kompilieren und führen Sie es.

  3. Sobald erfolgreich ausgeführt wurden, in den Ordner, in dem Sie Ihre gcc-Compiler und geben die

    installiert haben

    folgender Befehl erhält eine ‚.s‘ Datei der ‚.c‘ Datei

    C: \ gcc> gcc -S vollständigen Pfad der C-Datei ENTER

    Ein Beispiel Befehl (wie in meinem Fall)

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

    Das gibt eine '.s' Akte der ursprünglichen '.c' Datei

4. Danach geben Sie den folgenden Befehl

C; \ gcc> cav filename.s ENTER

Beispiel-Befehl (wie in meinem Fall)

C; \ gcc> cav alternate_letters.s

Das wird Druck / Ausgabe des gesamten Assembler-Code Ihres C-Programms.

Verwenden Sie "ES" als Option. Es zeigt die Montage im Terminal ausgegeben.

vor kurzem wollte ich die Montage der einzelnen Funktionen in einem Programm
wissen Dies ist, wie ich es tat.

$ 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

-save-temps

Dies wurde unter https://stackoverflow.com/a/17083009/895245 aber lassen Sie mich es weiter erläutern . 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 nun, neben der normalen Ausgabe main.o enthält das aktuelle Arbeitsverzeichnis auch die folgenden Dateien:

  • main.i ist ein Bonus und enthält die gewünschte vorbesessen-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 erzeugte 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 es für eine große Anzahl von Dateien tun mögen, sollte anstelle:

 -save-temps=obj

, die speichert die Zwischen Dateien in das gleiche Verzeichnis wie die -o Objektausgabe anstelle des aktuellen Arbeitsverzeichnis, so dass potenzielle Konflikte zu vermeiden Basisnamen.

Der Vorteil dieser Option über -S ist, dass es einfach ist, es jedem Build-Skript zu schreiben, ohne sich viel in den Aufbau zu stören.

Eine andere kühle Sache über diese Option ist, wenn Sie -v hinzufügen:

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

es zeigt tatsächlich die expliziten Dateien anstelle von hässlichen Provisorien unter /tmp verwendet werden, so ist es einfach, genau zu wissen, was los ist, der die Vorverarbeitung / Kompilierung / Montageschritte beinhaltet:

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

Hier ist eine Lösung für C mit gcc:

gcc -S program.c && gcc program.c -o output
  1. Hier der erste Teil speichert die Montag Ausgabe des Programms in dem gleichen Dateinamen wie Programm, aber mit einem veränderten .s Erweiterung, können Sie es wie jede normale Textdatei öffnen.

  2. Der zweite Teil hier kompiliert Ihr Programm für die tatsächliche Nutzung und erzeugt eine ausführbare Datei für Ihr Programm mit einem bestimmten Dateinamen.

Die programm.c verwendet oben ist der Name des Programms und Ausgang ist der Name der ausführbaren Datei Sie erzeugen möchten.

BTW Es ist mein erster Beitrag auf Stackoverflow: -}

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top