Yanıtlar:
-S
Gcc (veya g ++) seçeneğini kullanın .
gcc -S helloworld.c
Bu işlem ön işlemciyi (cpp) helloworld.c üzerinde çalıştıracak, ilk derlemeyi gerçekleştirecek ve sonra derleyici çalıştırılmadan duracaktır.
Varsayılan olarak bu bir dosya çıktısı verir helloworld.s
. Çıktı dosyası yine de -o
seçenek kullanılarak ayarlanabilir .
gcc -S -o my_asm_output.s helloworld.c
Tabii ki bu sadece orijinal kaynağınız varsa çalışır. Alternatifi, yalnızca sonuçta oluşan nesne dosyanız varsa, seçeneği objdump
ayarlayarak --disassemble
(veya -d
kısaltılmış form için) kullanmaktır.
objdump -S --disassemble helloworld > helloworld.dump
Nesne dosyası için hata ayıklama seçeneği etkinse ( -g
derleme zamanında) ve dosya çıkarılmadıysa, bu seçenek en iyi sonucu verir .
Koşu file helloworld
, objdump kullanarak alacağınız ayrıntı seviyesi hakkında size bir fikir verecektir.
.intel_syntax
olduğu değil NASM'ın ile uyumlu . Daha çok MASM'ye benzer (örneğin mov eax, symbol
, mov r32, imm32
adresin bulunduğu NASM'den farklı olarak bir yüktür ), ancak MASM ile tamamen uyumlu değildir. Özellikle NASM sözdiziminde yazmak isterseniz, okumak için güzel bir format olarak tavsiye ederim. objdump -drwC -Mintel | less
veya gcc foo.c -O1 -fverbose-asm -masm=intel -S -o- | less
faydalıdır. (Ayrıca bkz. “Gürültü” GCC / clang montaj çıkışından nasıl çıkarılır? ). -masm=intel
clang ile de çalışır.
gcc -O -fverbose-asm -S
Bu, hangi satırların hangi kodu ürettiğini daha kolay görmek için C kodu + satır numaraları birbirine bağlı olarak montaj kodu oluşturur:
# 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
Programcılar için Algoritmalar bölümünde bulunur , sayfa 3 (PDF'nin genel 15. sayfasıdır).
as
OS X'te bu bayrakları bilmiyor. Eğer öyleyse, -Wa
seçenekleri geçmek için bunu muhtemelen tek satırlık yapabilirsiniz as
.
g++ -g -O0 -c -fverbose-asm -Wa,-adhln test.cpp > test.lst
bunun kısa el versiyonu olacaktı.
gcc -c -g -Wa,-ahl=test.s test.c
veyagcc -c -g -Wa,-a,-ad test.c > test.txt
-O0
? Bu, bir değeri izlemeyi zorlaştıran yükler / mağazalarla doludur ve size optimize edilmiş kodun ne kadar verimli olacağı hakkında hiçbir şey söylemez.
Aşağıdaki komut satırı Christian Garbin'in blogundan
g++ -g -O -Wa,-aslh horton_ex2_05.cpp >list.txt
Gizli bir döküm içeren bir rutin karşı Win-XP üzerinde bir DOS penceresinden G ++ koştum
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'
Çıktı, orijinal C ++ koduyla birlikte dağıtılan oluşturulan kod olarak birleştirilir (C ++ kodu, oluşturulan asm akışında yorum olarak gösterilir)
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)
-O2
Gcc'nin kodunuzu nasıl optimize ettiğini görmek istiyorsanız, en azından veya projenizi oluştururken kullandığınız optimizasyon seçeneklerini kullanın. (Ya da LTO kullanıyorsanız, gerektiği gibi, o zaman gerçekten ne elde etmek için linker çıkışını sökmeniz gerekir.)
Görmek istediğiniz şey çıktının bağlantısına bağlıysa, yukarıda belirtilen gcc -S'ye ek olarak çıktı nesnesi dosyası / yürütülebilir dosyasına objdump da yararlı olabilir. Loren Merritt'in varsayılan objdump sözdizimini daha okunabilir nasm sözdizimine dönüştüren çok kullanışlı bir komut dosyası:
#!/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;
Bunun gcc -S çıktısında da kullanılabileceğinden şüpheleniyorum.
mov eax,ds:0x804b794
çok NASMish değildir. Ayrıca, bazen sadece faydalı bilgiler şeritler: movzx eax,[edx+0x1]
hafıza işlenen olup olmadığını tahmin etmek okuyucuya bırakır byte
ya word
.
objconv
kullanın . Çıktı dosyası = ile stdout'a ayırmayı /dev/stdout
başarabilirsiniz, böylece less
görüntüleme için boru oluşturabilirsiniz . Ayrıca var ndisasm
, ancak sadece düz ikili dosyaları söküyor ve nesne dosyaları (ELF / PE) hakkında bilgi sahibi değil.
Herkesin işaret ettiği gibi, -S
GCC seçeneğini kullanın. Ayrıca sonuçlar (çılgınca!) Optimizasyon seçenekleri ekleyip eklemediğinize ( -O0
hiçbiri -O2
için, agresif optimizasyon için ) bağlı olarak değişebilir eklemek istiyorum .
Özellikle RISC mimarilerinde, derleyici genellikle kodu optimizasyonda tanınmanın neredeyse ötesine dönüştürecektir. Sonuçlara bakmak etkileyici ve büyüleyici!
Daha önce de belirtildiği gibi, -S bayrağına bakın.
Ayrıca, gcc'nin ara formlarını görmenizi sağlayan '-fdump-tree' bayrak ailesine, özellikle '-fdump-tree-all' a bakmaya değer. Bunlar genellikle montajcıdan (en azından benim için) daha okunabilir olabilir ve optimizasyon geçişlerinin nasıl performans gösterdiğini görmenizi sağlar.
Bu olasılığı cevaplar arasında görmüyorum, muhtemelen soru 2008'den geliyor, ancak 2018'de Matt Goldbolt'un çevrimiçi web sitesini kullanabilirsiniz https://godbolt.org
Ayrıca yerel olarak klonla git ve projesini yürütebilirsiniz https://github.com/mattgodbolt/compiler-explorer
-save-temps
Bu, https://stackoverflow.com/a/17083009/895245 adresinde belirtildi, ancak daha fazla örnek vereyim.
Bu seçeneğin en büyük avantajı -S
, yapının kendisine çok fazla müdahale etmeden herhangi bir yapı komut dosyasına eklemenin çok kolay olmasıdır.
Yaptığınızda:
gcc -save-temps -c -o main.o main.c
main.c
#define INC 1
int myfunc(int i) {
return i + INC;
}
ve şimdi, normal çıktının yanı sıra, main.o
geçerli çalışma dizini aşağıdaki dosyaları da içerir:
main.i
bir bonus ve önceden aktarılmış dosyayı içerir:
# 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
istenen oluşturulmuş montajı içerir:
.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
Çok sayıda dosya için yapmak istiyorsanız, bunun yerine kullanmayı düşünün:
-save-temps=obj
ara dosyaları -o
geçerli çalışma dizini yerine nesne çıktısıyla aynı dizine kaydederek olası temel ad çakışmalarını önler.
Bu seçenekle ilgili bir başka harika şey de eklerseniz -v
:
gcc -save-temps -c -o main.o -v main.c
aslında altında çirkin geçiciler yerine kullanılan açık dosyaları gösterir /tmp
, bu yüzden önişleme / derleme / montaj adımlarını içeren tam olarak ne olduğunu bilmek kolaydır:
/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
Ubuntu 19.04 amd64, GCC 8.3.0'da test edilmiştir.
-S seçeneğini kullanın:
gcc -S program.c
Gönderen: http://www.delorie.com/djgpp/v2faq/faq8_20.html
gcc -c -g -Wa, -a, -ad [diğer GCC seçenekleri] foo.c> foo.lst
Veya PhirePhly'nin cevabına alternatif olarak veya herkesin söylediği gibi -S kullanın
Windows'unuzdaki herhangi bir C programının montaj kodunu görmek / yazdırmak için adımlar
konsol / terminal / komut istemi:
Codeblocks gibi bir C kodu düzenleyicisine bir C programı yazın ve bir uzantıyla kaydedin. C
Derleyin ve çalıştırın.
Başarılı bir şekilde çalıştırıldıktan sonra, gcc derleyicinizi kurduğunuz klasöre gidin ve
'.c' dosyasının '.s' dosyasını almak için aşağıdaki komut
C: \ gcc> gcc -C dosyasının tam yolu ENTER
Örnek bir komut (benim durumumda olduğu gibi)
C: \ gcc> gcc -SD: \ Aa_C_Certified \ alternate_letters.c
Bu, özgün '.c' dosyasının '.s' dosyasını verir
4. Bundan sonra aşağıdaki komutu yazın
C; \ gcc> cpp dosyaadı.s ENTER
Örnek komut (benim durumumda olduğu gibi)
C; \ gcc> cpp alternate_letters.s
Bu, C programınızın tüm Meclis dil kodunu basar / çıkarır.
Seçenek olarak "-S" kullanın. Terminalde montaj çıkışını görüntüler.
gcc foo.c -masm=intel -fverbose-asm -O3 -S -o- |less
. -S
kendi başına yaratır foo.s
.
Son zamanlarda bir programda her fonksiyonların montajını bilmek istedim
bu nasıl yaptım.
$ 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
İşte gcc kullanan C için bir çözüm:
gcc -S program.c && gcc program.c -o output
Burada ilk bölüm, programın derleme çıktısını Program ile aynı dosya adında depolar, ancak değiştirilmiş .s uzantısıyla, herhangi bir normal metin dosyası olarak açabilirsiniz.
Buradaki ikinci bölüm, programınızı gerçek kullanım için derler ve Programınız için belirtilen bir dosya adıyla yürütülebilir bir dosya oluşturur.
Program.c Yukarıda kullandığınız programın adıdır ve çıkış oluşturmak istediğiniz yürütülebilir adıdır.
BTW StackOverFlow'daki ilk yazım: -}