Wie kann man das tun?
Wenn ich analysieren möchte, wie etwas kompiliert wird, wie erhalte ich dann den emittierten Assemblercode?
Wie kann man das tun?
Wenn ich analysieren möchte, wie etwas kompiliert wird, wie erhalte ich dann den emittierten Assemblercode?
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.
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).
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)
-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 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.