Ini akan menjalankan preprocessor (cpp) di helloworld.c, melakukan kompilasi awal dan kemudian berhenti sebelum assembler dijalankan.
Secara default ini akan menghasilkan file helloworld.s. File output masih dapat diatur dengan menggunakan -oopsi.
gcc -S -o my_asm_output.s helloworld.c
Tentu saja ini hanya berfungsi jika Anda memiliki sumber aslinya. Alternatif jika Anda hanya memiliki file objek yang dihasilkan untuk digunakan objdump, dengan mengatur --disassembleopsi (atau -duntuk bentuk disingkat).
Meskipun ini benar, saya menemukan hasil dari jawaban Cr McDonough lebih bermanfaat.
Rhys Ulerich
3
tambahan gunakan: objdump -M intel -S --disassemble helloworld> helloworld.dump untuk mendapatkan objek dump di sintaks intel yang kompatibel dengan nasm di linux.
touchStone
2
Jika Anda memiliki fungsi tunggal untuk mengoptimalkan / memeriksa, maka Anda dapat mencoba interaktif C ++ Compiler online yaitu godbolt
fiorentinoing
1
@touchStone: GAS .intel_syntaxadalah tidak kompatibel dengan NASM . Ini lebih seperti MASM (misalnya mov eax, symbolbeban, tidak seperti di NASM yang merupakan mov r32, imm32alamatnya), tetapi tidak sepenuhnya kompatibel dengan MASM. Saya sangat merekomendasikan ini sebagai format yang bagus untuk dibaca, terutama jika Anda suka menulis dalam sintaks NASM. objdump -drwC -Mintel | lessatau gcc foo.c -O1 -fverbose-asm -masm=intel -S -o- | lessbermanfaat. (Lihat juga Bagaimana menghapus "noise" dari GCC / output rakitan? ). -masm=intelbekerja dengan dentang juga.
Peter Cordes
3
Penggunaan yang lebih baikgcc -O -fverbose-asm -S
Basile Starynkevitch
173
Ini akan menghasilkan kode rakitan dengan kode C + nomor baris terjalin, untuk lebih mudah melihat baris mana yang menghasilkan kode apa:
(Itu sebenarnya pada halaman (bernomor) 3 (yang merupakan halaman ke-15 dari PDF)
Grumdrig
1
Sayangnya, asdi OS X tidak tahu flag-flag ini. Namun, jika ya, Anda mungkin bisa menggunakan satu-line ini -Wauntuk meneruskan opsi as.
Grumdrig
23
g++ -g -O0 -c -fverbose-asm -Wa,-adhln test.cpp > test.lstakan menjadi versi singkat ini.
legends2k
4
Anda juga dapat menggunakan gcc -c -g -Wa,-ahl=test.s test.cataugcc -c -g -Wa,-a,-ad test.c > test.txt
phuclv
1
Sebuah posting blog yang menjelaskan ini lebih rinci, termasuk versi satu-perintah seperti legenda dan Lu'u diposting. Tapi mengapa -O0? Itu penuh dengan banyak / toko yang membuatnya sulit untuk melacak nilai, dan tidak memberi tahu Anda seberapa efisien kode yang dioptimalkan.
Saya menjalankan G ++ dari jendela DOS pada Win-XP, terhadap rutin yang berisi pemeran tersirat
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'
Keluarannya adalah kode yang dihasilkan assassembed diselingi dengan kode C ++ asli (kode C ++ ditampilkan sebagai komentar dalam aliran asm yang dihasilkan)
@Paladin - Belum tentu. OP adalah tentang mendapatkan setara assembler output dari kode sumber C / C ++, ini mendapat Listing, yang saya setuju lebih berguna untuk memahami apa yang dilakukan kompiler dan pengoptimal. Tapi itu akan menyebabkan assembler itu sendiri muntah, karena tidak mengharapkan nomor baris, dan menyusun byte dari total yang dia tinggalkan dari instruksi perakitan.
Jesse Chisholm
Gunakan setidaknya -O2, atau opsi pengoptimalan apa pun yang sebenarnya Anda gunakan saat membangun proyek Anda, jika Anda ingin melihat bagaimana gcc mengoptimalkan kode Anda. (Atau jika Anda menggunakan KPP, seperti yang seharusnya, maka Anda harus membongkar output linker untuk melihat apa yang benar-benar Anda dapatkan.)
Periksa FAQ: "Bertanya juga baik-baik saja untuk bertanya dan menjawab pertanyaan pemrograman Anda sendiri". Intinya adalah bahwa sekarang StackOverflow berisi Q&A sebagai sumber daya bagi orang lain.
Steve Jessop
Dan mungkin orang lain akan datang dan mengejutkan Anda dengan jawaban yang lebih baik, meskipun jawaban saya mungkin sedikit bertele-tele ...
PhirePhly
Bahkan ada jawaban tombol pertanyaan Anda sendiri.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
13
Jika apa yang ingin Anda lihat tergantung pada penautan output, maka objdump pada file objek output / executable juga dapat berguna selain gcc -S yang disebutkan di atas. Berikut ini skrip yang sangat berguna dari Loren Merritt yang mengubah sintaks objdump default menjadi sintaks nasm yang lebih mudah dibaca:
#!/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;
Saya menduga ini juga dapat digunakan pada output gcc -S.
Namun, skrip ini adalah hack kotor yang tidak sepenuhnya mengonversi sintaksis. Misalnya mov eax,ds:0x804b794tidak terlalu NASMish. Juga, kadang-kadang itu hanya menghapus informasi yang berguna: movzx eax,[edx+0x1]membuat pembaca menebak apakah operan memori itu byteatau tidak word.
Ruslan
Untuk membongkar sintaks NASM sejak awal, gunakan Agner Fog'sobjconv . Anda bisa membuatnya untuk membongkar ke stdout dengan file output = /dev/stdout, sehingga Anda dapat pipa keless untuk dilihat. Ada juga ndisasm, tetapi hanya membongkar binari datar, dan tidak tahu tentang file objek (ELF / PE).
Peter Cordes
9
Seperti yang semua orang tunjukkan, gunakan -Sopsi untuk GCC. Saya juga ingin menambahkan bahwa hasilnya dapat bervariasi (liar!) Tergantung pada apakah Anda menambahkan opsi pengoptimalan ( -O0tidak ada, -O2untuk pengoptimalan yang agresif).
Pada arsitektur RISC pada khususnya, kompiler akan sering mengubah kode hampir tidak dapat dikenali dalam melakukan optimasi. Sangat mengesankan dan menarik untuk melihat hasilnya!
Nah, seperti kata semua orang, gunakan opsi -S. Jika Anda menggunakan opsi -simpan-temps, Anda juga bisa mendapatkan file preprocessed ( .i), file assembly ( .s) dan file objek (*. O). (dapatkan masing-masing dengan menggunakan -E, -S, dan -c.)
Perlu juga melihat keluarga flag '-fdump-tree', khususnya '-fdump-tree-all', yang memungkinkan Anda melihat beberapa bentuk peralihan gcc. Ini sering kali lebih mudah dibaca daripada assembler (setidaknya bagi saya), dan biarkan Anda melihat bagaimana optimasi berjalan.
Saya tidak melihat kemungkinan ini di antara jawaban, mungkin karena pertanyaannya adalah dari tahun 2008, tetapi pada tahun 2018 Anda dapat menggunakan situs web online Matt Goldbolt https://godbolt.org
Keuntungan besar dari opsi ini berakhir -S ini adalah sangat mudah untuk menambahkannya ke skrip build apa pun, tanpa banyak campur tangan dalam build itu sendiri.
Saat kamu melakukan:
gcc -save-temps -c -o main.o main.c
main.c
#define INC 1int myfunc(int i){return i + INC;}
dan sekarang, selain output normal main.o, direktori kerja saat ini juga berisi file-file berikut:
main.i adalah bonus dan berisi file preprossessed:
Jika Anda ingin melakukannya untuk banyak file, pertimbangkan untuk menggunakan:
-save-temps=obj
yang menyimpan file-file antara ke direktori yang sama dengan -ooutput objek alih-alih direktori kerja saat ini, sehingga menghindari kemungkinan konflik nama nama.
Hal keren lainnya tentang opsi ini adalah jika Anda menambahkan -v:
gcc -save-temps -c -o main.o -v main.c
itu benar-benar menunjukkan file eksplisit yang digunakan alih-alih temporari jelek di bawah /tmp, sehingga mudah untuk mengetahui apa yang sedang terjadi, yang meliputi langkah preprocessing / kompilasi / perakitan:
Untuk ditampilkan di terminal, gunakan gcc foo.c -masm=intel -fverbose-asm -O3 -S -o- |less. -Sdengan sendirinya menciptakan foo.s.
Peter Cordes
2
Baru-baru ini saya ingin mengetahui perakitan dari masing-masing fungsi dalam suatu program.
Ini adalah bagaimana saya melakukannya.
$ 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
Di sini bagian pertama menyimpan output rakitan program dalam nama file yang sama dengan Program tetapi dengan ekstensi .s yang diubah , Anda dapat membukanya sebagai file teks biasa.
Bagian kedua di sini mengkompilasi program Anda untuk penggunaan aktual dan menghasilkan executable untuk Program Anda dengan nama file yang ditentukan.
The program.c digunakan di atas adalah nama program dan keluaran adalah nama executable Anda ingin menghasilkan.
Jawaban:
Gunakan
-S
opsi untuk gcc (atau g ++).Ini akan menjalankan preprocessor (cpp) di helloworld.c, melakukan kompilasi awal dan kemudian berhenti sebelum assembler dijalankan.
Secara default ini akan menghasilkan file
helloworld.s
. File output masih dapat diatur dengan menggunakan-o
opsi.Tentu saja ini hanya berfungsi jika Anda memiliki sumber aslinya. Alternatif jika Anda hanya memiliki file objek yang dihasilkan untuk digunakan
objdump
, dengan mengatur--disassemble
opsi (atau-d
untuk bentuk disingkat).Opsi ini berfungsi paling baik jika opsi debugging diaktifkan untuk file objek (
-g
pada waktu kompilasi) dan file belum dilucuti.Menjalankan
file helloworld
akan memberi Anda beberapa indikasi tentang tingkat detail yang akan Anda dapatkan dengan menggunakan objdump.sumber
.intel_syntax
adalah tidak kompatibel dengan NASM . Ini lebih seperti MASM (misalnyamov eax, symbol
beban, tidak seperti di NASM yang merupakanmov r32, imm32
alamatnya), tetapi tidak sepenuhnya kompatibel dengan MASM. Saya sangat merekomendasikan ini sebagai format yang bagus untuk dibaca, terutama jika Anda suka menulis dalam sintaks NASM.objdump -drwC -Mintel | less
ataugcc foo.c -O1 -fverbose-asm -masm=intel -S -o- | less
bermanfaat. (Lihat juga Bagaimana menghapus "noise" dari GCC / output rakitan? ).-masm=intel
bekerja dengan dentang juga.gcc -O -fverbose-asm -S
Ini akan menghasilkan kode rakitan dengan kode C + nomor baris terjalin, untuk lebih mudah melihat baris mana yang menghasilkan kode apa:
Ditemukan dalam Algoritma untuk programmer , halaman 3 (yang merupakan halaman ke 15 keseluruhan dari PDF).
sumber
as
di OS X tidak tahu flag-flag ini. Namun, jika ya, Anda mungkin bisa menggunakan satu-line ini-Wa
untuk meneruskan opsias
.g++ -g -O0 -c -fverbose-asm -Wa,-adhln test.cpp > test.lst
akan menjadi versi singkat ini.gcc -c -g -Wa,-ahl=test.s test.c
ataugcc -c -g -Wa,-a,-ad test.c > test.txt
-O0
? Itu penuh dengan banyak / toko yang membuatnya sulit untuk melacak nilai, dan tidak memberi tahu Anda seberapa efisien kode yang dioptimalkan.Baris perintah berikut ini dari blog Christian Garbin
Saya menjalankan G ++ dari jendela DOS pada Win-XP, terhadap rutin yang berisi pemeran tersirat
Keluarannya adalah kode yang dihasilkan assassembed diselingi dengan kode C ++ asli (kode C ++ ditampilkan sebagai komentar dalam aliran asm yang dihasilkan)
sumber
-O2
, atau opsi pengoptimalan apa pun yang sebenarnya Anda gunakan saat membangun proyek Anda, jika Anda ingin melihat bagaimana gcc mengoptimalkan kode Anda. (Atau jika Anda menggunakan KPP, seperti yang seharusnya, maka Anda harus membongkar output linker untuk melihat apa yang benar-benar Anda dapatkan.)Gunakan tombol -S
atau juga dengan gcc
Lihat juga ini
sumber
Jika apa yang ingin Anda lihat tergantung pada penautan output, maka objdump pada file objek output / executable juga dapat berguna selain gcc -S yang disebutkan di atas. Berikut ini skrip yang sangat berguna dari Loren Merritt yang mengubah sintaks objdump default menjadi sintaks nasm yang lebih mudah dibaca:
Saya menduga ini juga dapat digunakan pada output gcc -S.
sumber
mov eax,ds:0x804b794
tidak terlalu NASMish. Juga, kadang-kadang itu hanya menghapus informasi yang berguna:movzx eax,[edx+0x1]
membuat pembaca menebak apakah operan memori itubyte
atau tidakword
.objconv
. Anda bisa membuatnya untuk membongkar ke stdout dengan file output =/dev/stdout
, sehingga Anda dapat pipa keless
untuk dilihat. Ada jugandisasm
, tetapi hanya membongkar binari datar, dan tidak tahu tentang file objek (ELF / PE).Seperti yang semua orang tunjukkan, gunakan
-S
opsi untuk GCC. Saya juga ingin menambahkan bahwa hasilnya dapat bervariasi (liar!) Tergantung pada apakah Anda menambahkan opsi pengoptimalan (-O0
tidak ada,-O2
untuk pengoptimalan yang agresif).Pada arsitektur RISC pada khususnya, kompiler akan sering mengubah kode hampir tidak dapat dikenali dalam melakukan optimasi. Sangat mengesankan dan menarik untuk melihat hasilnya!
sumber
Nah, seperti kata semua orang, gunakan opsi -S. Jika Anda menggunakan opsi -simpan-temps, Anda juga bisa mendapatkan file preprocessed ( .i), file assembly ( .s) dan file objek (*. O). (dapatkan masing-masing dengan menggunakan -E, -S, dan -c.)
sumber
Seperti disebutkan sebelumnya, lihat bendera -S.
Perlu juga melihat keluarga flag '-fdump-tree', khususnya '-fdump-tree-all', yang memungkinkan Anda melihat beberapa bentuk peralihan gcc. Ini sering kali lebih mudah dibaca daripada assembler (setidaknya bagi saya), dan biarkan Anda melihat bagaimana optimasi berjalan.
sumber
Jika Anda mencari perakitan LLVM:
sumber
Saya tidak melihat kemungkinan ini di antara jawaban, mungkin karena pertanyaannya adalah dari tahun 2008, tetapi pada tahun 2018 Anda dapat menggunakan situs web online Matt Goldbolt https://godbolt.org
Anda juga dapat klon git secara lokal dan menjalankan proyeknya https://github.com/mattgodbolt/compiler-explorer
sumber
-save-temps
Ini disebutkan di https://stackoverflow.com/a/17083009/895245 tetapi biarkan saya mencontohkan lebih lanjut.
Keuntungan besar dari opsi ini berakhir
-S
ini adalah sangat mudah untuk menambahkannya ke skrip build apa pun, tanpa banyak campur tangan dalam build itu sendiri.Saat kamu melakukan:
main.c
dan sekarang, selain output normal
main.o
, direktori kerja saat ini juga berisi file-file berikut:main.i
adalah bonus dan berisi file preprossessed:main.s
mengandung rakitan yang dihasilkan yang diinginkan:Jika Anda ingin melakukannya untuk banyak file, pertimbangkan untuk menggunakan:
yang menyimpan file-file antara ke direktori yang sama dengan
-o
output objek alih-alih direktori kerja saat ini, sehingga menghindari kemungkinan konflik nama nama.Hal keren lainnya tentang opsi ini adalah jika Anda menambahkan
-v
:itu benar-benar menunjukkan file eksplisit yang digunakan alih-alih temporari jelek di bawah
/tmp
, sehingga mudah untuk mengetahui apa yang sedang terjadi, yang meliputi langkah preprocessing / kompilasi / perakitan:Diuji di Ubuntu 19.04 amd64, GCC 8.3.0.
sumber
Gunakan opsi -S:
sumber
Dari: http://www.delorie.com/djgpp/v2faq/faq8_20.html
gcc -c -g -Wa, -a, -ad [opsi GCC lain] foo.c> foo.lst
sebagai alternatif dari jawaban PhirePhly Atau gunakan saja -S seperti yang dikatakan semua orang.
sumber
Berikut adalah langkah-langkah untuk melihat / mencetak kode rakitan dari setiap program C pada Windows Anda
konsol / terminal / command prompt:
Tulis program C dalam editor kode C seperti kode kunci dan simpan dengan ekstensi .c
Kompilasi dan jalankan.
Setelah berjalan dengan sukses, buka folder tempat Anda menginstal kompiler gcc Anda dan berikan
mengikuti perintah untuk mendapatkan file '.s' dari file '.c'
C: \ gcc> gcc -S lintasan lengkap file C ENTER
Contoh perintah (seperti dalam kasus saya)
C: \ gcc> gcc -SD: \ Aa_C_Certified \ alternate_letters.c
Ini menghasilkan file '.s' dari file '.c' yang asli
4. Setelah ini, ketikkan perintah berikut
C; \ gcc> cpp filename.s ENTER
Contoh perintah (seperti dalam kasus saya)
C; \ gcc> cpp alternate_letters.s
Ini akan mencetak / menampilkan seluruh kode bahasa Assembly program C. Anda.
sumber
Gunakan "-S" sebagai opsi. Ini menampilkan output perakitan di terminal.
sumber
gcc foo.c -masm=intel -fverbose-asm -O3 -S -o- |less
.-S
dengan sendirinya menciptakanfoo.s
.Baru-baru ini saya ingin mengetahui perakitan dari masing-masing fungsi dalam suatu program.
Ini adalah bagaimana saya melakukannya.
sumber
Berikut adalah solusi untuk C menggunakan gcc:
Di sini bagian pertama menyimpan output rakitan program dalam nama file yang sama dengan Program tetapi dengan ekstensi .s yang diubah , Anda dapat membukanya sebagai file teks biasa.
Bagian kedua di sini mengkompilasi program Anda untuk penggunaan aktual dan menghasilkan executable untuk Program Anda dengan nama file yang ditentukan.
The program.c digunakan di atas adalah nama program dan keluaran adalah nama executable Anda ingin menghasilkan.
BTW Ini posting pertama saya di StackOverFlow: -}
sumber