Dadurch wird der Präprozessor (cpp) über helloworld.c ausgeführt, die erste Kompilierung durchgeführt und dann gestoppt, bevor der Assembler ausgeführt wird.
Standardmäßig wird eine Datei ausgegeben helloworld.s. Die Ausgabedatei kann weiterhin mit der -oOption eingestellt werden.
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 objdump, indem Sie die --disassembleOption (oder -dfür das abgekürzte Formular) festlegen.
Diese Option funktioniert am besten, wenn die Debugging-Option für die Objektdatei ( -gzur Kompilierungszeit) aktiviert ist und die Datei nicht entfernt wurde.
Wenn Sie ausgeführt file helloworldwerden, erhalten Sie einen Hinweis auf den Detaillierungsgrad, den Sie mit objdump erhalten.
Obwohl dies korrekt ist, fand ich die Ergebnisse von Cr McDonoughs Antwort nützlicher.
Rhys Ulerich
3
Verwenden Sie zusätzlich: objdump -M intel -S --disassemble helloworld> helloworld.dump, um den Objektspeicherauszug in Intel-Syntax abzurufen, die mit nasm unter Linux kompatibel ist.
touchStone
2
Wenn Sie eine einzelne Funktion zu optimieren / Check haben, dann können Sie einen Versuch zu Online Interactive C ++ Compiler also geben Godbolt
fiorentinoing
1
@touchStone: GAS .intel_syntaxist nicht mit NASM kompatibel . Es ist eher wie MASM (z. B. mov eax, symboleine Last, im Gegensatz zu NASM, wo es sich um eine mov r32, imm32Adresse handelt), aber auch nicht vollständig mit MASM kompatibel. Ich empfehle es sehr als schönes Format zum Lesen, besonders wenn Sie jedoch in NASM-Syntax schreiben möchten. objdump -drwC -Mintel | lessoder gcc foo.c -O1 -fverbose-asm -masm=intel -S -o- | lesssind nützlich. (Siehe auch Entfernen von „Rauschen“ von der Ausgabe der GCC / Clang-Baugruppe? ) -masm=intelfunktioniert auch mit clang.
Peter Cordes
3
Bessere Verwendunggcc -O -fverbose-asm -S
Basile Starynkevitch
173
Dadurch wird ein Assembler-Code mit verwobenem C-Code + Zeilennummern generiert, um leichter zu erkennen, welche Zeilen welchen Code generieren:
(Das ist tatsächlich auf Seite (nummeriert) 3 (das ist die 15. Seite des PDF))
Grumdrig
1
Leider askennt OS X diese Flags unter OS X nicht. In diesem Fall könnten Sie dies wahrscheinlich einzeilig verwenden -Wa, um Optionen an zu übergeben as.
Sie können auch entweder gcc -c -g -Wa,-ahl=test.s test.codergcc -c -g -Wa,-a,-ad test.c > test.txt
phuclv
1
Ein Blog-Beitrag , der dies ausführlicher erklärt, einschließlich der Ein-Befehl-Version wie Legenden und Lu'u. Aber warum -O0? Das ist voll von Lasten / Speichern, die es schwierig machen, einen Wert zu verfolgen, und sagt nichts darüber aus, wie effizient der optimierte Code sein wird.
Ich habe G ++ in 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:Infunction`int main()':
horton_ex2_05.cpp:92: warning: assignment to `int' from `double'
Die Ausgabe besteht aus zusammengesetztem generiertem Code, der mit dem ursprünglichen C ++ - Code durchsetzt ist (der C ++ - Code wird als Kommentare im generierten asm-Stream angezeigt).
@ Paladin - Nicht unbedingt. Beim OP ging es darum, das Assembler-Ausgabeäquivalent des C / C ++ - Quellcodes zu erhalten. Dadurch wird das Listing abgerufen, das meiner Meinung nach nützlicher ist, um zu verstehen, was der Compiler und der Optimierer tun. Dies würde jedoch dazu führen, dass der Assembler selbst barf, da er die Zeilennummern nicht erwartet und Bytes außerhalb der Assembler-Anweisungen kompiliert.
Jesse Chisholm
Verwenden Sie mindestens die -O2Optimierungsoptionen, die Sie beim Erstellen Ihres Projekts tatsächlich verwenden, wenn Sie sehen möchten, wie gcc Ihren Code optimiert. (Oder wenn Sie LTO verwenden, wie Sie sollten, dann müssen Sie die Linker-Ausgabe zerlegen, um zu sehen, was Sie wirklich bekommen.)
Überprüfen Sie die FAQ: "Es ist auch vollkommen in Ordnung, Ihre eigene Programmierfrage zu stellen und zu beantworten". Der Punkt ist, dass StackOverflow jetzt die Fragen und Antworten als Ressource für andere enthält.
Steve Jessop
Und vielleicht kommt jemand anderes und überrascht Sie mit einer besseren Antwort, obwohl meine manchmal etwas ausführlich sein könnte ...
PhirePhly
Es gibt sogar die Antwort auf Ihre eigene Frage-Schaltfläche.
Ciro Santilli 法轮功 冠状 病 六四 事件 24
13
Wenn das, was Sie sehen möchten, von der Verknüpfung der Ausgabe abhängt, kann objdump in der Ausgabeobjektdatei / ausführbaren Datei zusätzlich zu den oben genannten gcc -S auch 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',@ARGVordie;
$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.
Trotzdem ist dieses Skript ein schmutziger Hack, der die Syntax nicht vollständig konvertiert. ZB mov eax,ds:0x804b794ist nicht sehr NASMish. Manchmal werden auch nur nützliche Informationen entfernt: movzx eax,[edx+0x1]Der Leser kann erraten, ob der Speicheroperand warbyte oder nicht word.
Ruslan
Verwenden Sie, um die NASM-Syntax zunächst zu zerlegen Agner Fog'sobjconv . Sie können es mit der Ausgabedatei = in stdout zerlegen lassen /dev/stdout, damit Sie es lesszur Anzeige weiterleiten können. Es gibt auch ndisasm, aber es zerlegt nur flache Binärdateien und weiß nichts über Objektdateien (ELF / PE).
Peter Cordes
9
Wie jeder darauf hingewiesen hat, nutzen Sie die -SOption für GCC. Ich möchte auch hinzufügen, dass die Ergebnisse (stark!) Variieren können, je nachdem, ob Sie Optimierungsoptionen hinzufügen oder nicht ( -O0für keine, -O2für aggressive Optimierung).
Insbesondere bei RISC-Architekturen transformiert der Compiler den Code bei der Optimierung häufig fast bis zur Unkenntlichkeit. Es ist beeindruckend und faszinierend, die Ergebnisse zu betrachten!
Verwenden Sie, wie alle sagten, die Option -S. Wenn Sie die Option -save-temps verwenden, können Sie auch vorverarbeitete Dateien ( .i), Assembly-Dateien ( .s) und Objektdateien (*. O) abrufen. (Holen Sie sich jeden von ihnen mit -E, -S und -c.)
Schauen Sie sich, wie bereits erwähnt, die Flagge -S an.
Es lohnt sich auch, einen Blick auf die Flaggenfamilie '-fdump-tree' zu werfen, insbesondere auf '-fdump-tree-all', mit der Sie einige der Zwischenformen von gcc sehen können. Diese sind oft besser lesbar als Assembler (zumindest für mich) und lassen Sie sehen, wie Optimierungsdurchläufe funktionieren.
Ich sehe diese Möglichkeit nicht unter den Antworten, wahrscheinlich weil die Frage aus dem Jahr 2008 stammt, aber 2018 können Sie die Online-Website von Matt Goldbolt verwenden https://godbolt.org verwenden
Der große Vorteil dieser Option gegenüber -S ist, dass es sehr einfach ist, sie zu jedem Build-Skript hinzuzufügen, ohne den Build selbst stark zu beeinträchtigen.
Wenn Sie das tun:
gcc -save-temps -c -o main.o main.c
Haupt c
#define INC 1int myfunc(int i){return i + INC;}
und jetzt main.oenthält das aktuelle Arbeitsverzeichnis neben der normalen Ausgabe auch die folgenden Dateien:
main.i ist ein Bonus und enthält die vorverarbeitete Datei:
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 -oObjektausgabe anstelle des aktuellen Arbeitsverzeichnisses gespeichert , wodurch potenzielle Konflikte mit Basisnamen 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 Provisorien verwendet werden /tmp, so dass es einfach ist, genau zu wissen, was gerade passiert, einschließlich der Schritte Vorverarbeitung / Kompilierung / Assemblierung:
Verwenden Sie zum Anzeigen im Terminal gcc foo.c -masm=intel -fverbose-asm -O3 -S -o- |less. -Sauf eigene Faust schafft foo.s.
Peter Cordes
2
Vor kurzem wollte ich wissen, wie die einzelnen Funktionen in einem Programm zusammengesetzt
sind. So habe ich es gemacht.
$ 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
Hier speichert der erste Teil die Assembly-Ausgabe des Programms unter demselben Dateinamen wie Program, aber mit der geänderten Erweiterung .s können Sie sie wie jede normale Textdatei öffnen.
Der zweite Teil hier kompiliert Ihr Programm für die tatsächliche Verwendung und generiert eine ausführbare Datei für Ihr Programm mit einem angegebenen Dateinamen.
Das oben verwendete Programm.c ist der Name Ihres Programms und die Ausgabe ist der Name der ausführbaren Datei, die Sie generieren möchten.
Übrigens ist es mein erster Beitrag auf StackOverFlow: -}
Antworten:
Verwenden Sie die
-S
Option zu gcc (oder g ++).Dadurch wird der Präprozessor (cpp) über helloworld.c ausgeführt, die erste Kompilierung durchgeführt und dann gestoppt, bevor der Assembler ausgeführt wird.
Standardmäßig wird eine Datei ausgegeben
helloworld.s
. Die Ausgabedatei kann weiterhin mit der-o
Option eingestellt werden.Dies funktioniert natürlich nur, wenn Sie die Originalquelle haben. Eine Alternative, wenn Sie nur die resultierende Objektdatei haben, ist die Verwendung
objdump
, indem Sie die--disassemble
Option (oder-d
für das abgekürzte Formular) festlegen.Diese Option funktioniert am besten, wenn die Debugging-Option für die Objektdatei (
-g
zur Kompilierungszeit) aktiviert ist und die Datei nicht entfernt wurde.Wenn Sie ausgeführt
file helloworld
werden, erhalten Sie einen Hinweis auf den Detaillierungsgrad, den Sie mit objdump erhalten.quelle
.intel_syntax
ist nicht mit NASM kompatibel . Es ist eher wie MASM (z. B.mov eax, symbol
eine Last, im Gegensatz zu NASM, wo es sich um einemov r32, imm32
Adresse handelt), aber auch nicht vollständig mit MASM kompatibel. Ich empfehle es sehr als schönes Format zum Lesen, besonders wenn Sie jedoch in NASM-Syntax schreiben möchten.objdump -drwC -Mintel | less
odergcc foo.c -O1 -fverbose-asm -masm=intel -S -o- | less
sind nützlich. (Siehe auch Entfernen von „Rauschen“ von der Ausgabe der GCC / Clang-Baugruppe? )-masm=intel
funktioniert auch mit clang.gcc -O -fverbose-asm -S
Dadurch wird ein Assembler-Code mit verwobenem C-Code + Zeilennummern generiert, um leichter zu erkennen, welche Zeilen welchen Code generieren:
Gefunden in Algorithmen für Programmierer , Seite 3 (dies ist die 15. Gesamtseite des PDF).
quelle
as
kennt OS X diese Flags unter OS X nicht. In diesem Fall könnten Sie dies wahrscheinlich einzeilig verwenden-Wa
, um Optionen an zu übergebenas
.g++ -g -O0 -c -fverbose-asm -Wa,-adhln test.cpp > test.lst
wäre die Kurzhandversion davon.gcc -c -g -Wa,-ahl=test.s test.c
odergcc -c -g -Wa,-a,-ad test.c > test.txt
-O0
? Das ist voll von Lasten / Speichern, die es schwierig machen, einen Wert zu verfolgen, und sagt nichts darüber aus, wie effizient der optimierte Code sein wird.Die folgende Befehlszeile stammt aus Christian Garbins Blog
Ich habe G ++ in einem DOS-Fenster unter Win-XP gegen eine Routine ausgeführt, die eine implizite Umwandlung enthält
Die Ausgabe besteht aus zusammengesetztem generiertem Code, der mit dem ursprünglichen C ++ - Code durchsetzt ist (der C ++ - Code wird als Kommentare im generierten asm-Stream angezeigt).
quelle
-O2
Optimierungsoptionen, die Sie beim Erstellen Ihres Projekts tatsächlich verwenden, wenn Sie sehen möchten, wie gcc Ihren Code optimiert. (Oder wenn Sie LTO verwenden, wie Sie sollten, dann müssen Sie die Linker-Ausgabe zerlegen, um zu sehen, was Sie wirklich bekommen.)Verwenden Sie den -S-Schalter
oder auch mit gcc
Siehe auch dies
quelle
Wenn das, was Sie sehen möchten, von der Verknüpfung der Ausgabe abhängt, kann objdump in der Ausgabeobjektdatei / ausführbaren Datei zusätzlich zu den oben genannten gcc -S auch 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:
Ich vermute, dass dies auch für die Ausgabe von gcc -S verwendet werden kann.
quelle
mov eax,ds:0x804b794
ist nicht sehr NASMish. Manchmal werden auch nur nützliche Informationen entfernt:movzx eax,[edx+0x1]
Der Leser kann erraten, ob der Speicheroperand warbyte
oder nichtword
.objconv
. Sie können es mit der Ausgabedatei = in stdout zerlegen lassen/dev/stdout
, damit Sie esless
zur Anzeige weiterleiten können. Es gibt auchndisasm
, aber es zerlegt nur flache Binärdateien und weiß nichts über Objektdateien (ELF / PE).Wie jeder darauf hingewiesen hat, nutzen Sie die
-S
Option für GCC. Ich möchte auch hinzufügen, dass die Ergebnisse (stark!) Variieren können, je nachdem, ob Sie Optimierungsoptionen hinzufügen oder nicht (-O0
für keine,-O2
für aggressive Optimierung).Insbesondere bei RISC-Architekturen transformiert der Compiler den Code bei der Optimierung häufig fast bis zur Unkenntlichkeit. Es ist beeindruckend und faszinierend, die Ergebnisse zu betrachten!
quelle
Verwenden Sie, wie alle sagten, die Option -S. Wenn Sie die Option -save-temps verwenden, können Sie auch vorverarbeitete Dateien ( .i), Assembly-Dateien ( .s) und Objektdateien (*. O) abrufen. (Holen Sie sich jeden von ihnen mit -E, -S und -c.)
quelle
Schauen Sie sich, wie bereits erwähnt, die Flagge -S an.
Es lohnt sich auch, einen Blick auf die Flaggenfamilie '-fdump-tree' zu werfen, insbesondere auf '-fdump-tree-all', mit der Sie einige der Zwischenformen von gcc sehen können. Diese sind oft besser lesbar als Assembler (zumindest für mich) und lassen Sie sehen, wie Optimierungsdurchläufe funktionieren.
quelle
Wenn Sie nach einer LLVM-Baugruppe suchen:
quelle
Ich sehe diese Möglichkeit nicht unter den Antworten, wahrscheinlich weil die Frage aus dem Jahr 2008 stammt, aber 2018 können Sie die Online-Website von Matt Goldbolt verwenden https://godbolt.org verwenden
Sie können sein Projekt auch lokal klonen und sein Projekt https://github.com/mattgodbolt/compiler-explorer ausführen
quelle
-save-temps
Dies wurde unter https://stackoverflow.com/a/17083009/895245 erwähnt aber ich möchte es weiter veranschaulichen.
Der große Vorteil dieser Option gegenüber
-S
ist, dass es sehr einfach ist, sie zu jedem Build-Skript hinzuzufügen, ohne den Build selbst stark zu beeinträchtigen.Wenn Sie das tun:
Haupt c
und jetzt
main.o
enthält das aktuelle Arbeitsverzeichnis neben der normalen Ausgabe auch die folgenden Dateien:main.i
ist ein Bonus und enthält die vorverarbeitete Datei:main.s
enthält die gewünschte generierte Baugruppe:Wenn Sie dies für eine große Anzahl von Dateien tun möchten, sollten Sie stattdessen Folgendes verwenden:
Dadurch werden die Zwischendateien im selben Verzeichnis wie die
-o
Objektausgabe anstelle des aktuellen Arbeitsverzeichnisses gespeichert , wodurch potenzielle Konflikte mit Basisnamen vermieden werden.Eine weitere coole Sache an dieser Option ist, wenn Sie hinzufügen
-v
:Es zeigt tatsächlich die expliziten Dateien, die anstelle von hässlichen Provisorien verwendet werden
/tmp
, so dass es einfach ist, genau zu wissen, was gerade passiert, einschließlich der Schritte Vorverarbeitung / Kompilierung / Assemblierung:Getestet in Ubuntu 19.04 amd64, GCC 8.3.0.
quelle
Verwenden Sie die Option -S:
quelle
Von: http://www.delorie.com/djgpp/v2faq/faq8_20.html
gcc -c -g -Wa, -a, -ad [andere GCC-Optionen] foo.c> foo.lst
alternativ zu PhirePhlys Antwort Oder verwenden Sie einfach -S, wie alle sagten.
quelle
Hier sind die Schritte zum Anzeigen / Drucken des Assembler-Codes eines C-Programms unter Windows
Konsole / Terminal / Eingabeaufforderung:
Schreiben Sie ein C-Programm in einen C-Code-Editor wie Codeblöcke und speichern Sie es mit der Erweiterung .c
Kompilieren und ausführen.
Wechseln Sie nach erfolgreicher Ausführung zu dem Ordner, in dem Sie Ihren gcc-Compiler installiert haben, und geben Sie den ein
Der folgende Befehl ruft eine '.s'-Datei der' .c'-Datei ab
C: \ gcc> gcc -S Vollständiger Pfad der C-Datei ENTER
Ein Beispielbefehl (wie in meinem Fall)
C: \ gcc> gcc -SD: \ Aa_C_Certified \ alternative_letters.c
Dies gibt eine '.s'-Datei der ursprünglichen' .c'-Datei aus
4. Geben Sie danach den folgenden Befehl ein
C; \ gcc> cpp filename.s ENTER
Beispielbefehl (wie in meinem Fall)
C; \ gcc> cpp alternative_letters.s
Dadurch wird der gesamte Assembler-Code Ihres C-Programms gedruckt / ausgegeben.
quelle
Verwenden Sie optional "-S". Es zeigt die Baugruppenausgabe im Terminal an.
quelle
gcc foo.c -masm=intel -fverbose-asm -O3 -S -o- |less
.-S
auf eigene Faust schafftfoo.s
.Vor kurzem wollte ich wissen, wie die einzelnen Funktionen in einem Programm zusammengesetzt
sind. So habe ich es gemacht.
quelle
Hier ist eine Lösung für C mit gcc:
Hier speichert der erste Teil die Assembly-Ausgabe des Programms unter demselben Dateinamen wie Program, aber mit der geänderten Erweiterung .s können Sie sie wie jede normale Textdatei öffnen.
Der zweite Teil hier kompiliert Ihr Programm für die tatsächliche Verwendung und generiert eine ausführbare Datei für Ihr Programm mit einem angegebenen Dateinamen.
Das oben verwendete Programm.c ist der Name Ihres Programms und die Ausgabe ist der Name der ausführbaren Datei, die Sie generieren möchten.
Übrigens ist es mein erster Beitrag auf StackOverFlow: -}
quelle