2008-09-26 130 views
274

如何做到這一點?如何從gcc的C/C++源代碼獲得彙編程序輸出?

如果我想分析一些東西是如何編譯的,我將如何獲得發出的彙編代碼?

+6

有關**使asm輸出可讀**的提示,另請參閱:[如何從GCC/clang程序集輸出中刪除「noise」](http://stackoverflow.com/questions/38552116/how-從gcc-clang-assembly-output中刪除噪音) – 2016-07-26 04:30:06

回答

308

使用gcc(或g ++)的-S選項。

gcc -S helloworld.c 

這將運行在helloworld.c預處理器(CPP),執行初始編譯,然後運行彙編器之前停止。

默認情況下,這將輸出文件helloworld.s。輸出文件仍可通過使用-o選項進行設置。

gcc -S -o my_asm_output.s helloworld.c 

當然,這隻有在您有原始來源時纔有效。 如果只有生成的目標文件,則通過設置--disassemble選項(或-d的縮寫形式),使用objdump

objdump -S --disassemble helloworld > helloworld.dump 

如果調試選項是目標文件(-g在編譯時)啓用,該文件並沒有被剝奪,此選項效果最佳。

運行file helloworld會給你一些關於你將通過使用objdump獲得的詳細程度的指示。

+3

雖然這是正確的,但我發現Cr McDonough的答案更有用。 – 2013-11-03 02:13:02

+3

另外一個用途:objdump -M intel -S --disassemble helloworld> helloworld.dump以intel語法獲得對象轉儲,與linux上的nasm兼容。 – touchStone 2015-03-11 11:58:33

19

使用-s開關

g++ -S main.cpp 

,或者也用gcc

gcc -S main.c 

另見this

+6

查看常見問題解答:「問問題並回答你自己的編程問題也很好」。問題是現在,StackOverflow將Q&A作爲其他資源的資源。 – 2008-09-26 00:50:10

+0

也許別人會走過來,給你一個更好的答案給你一個驚喜,雖然我的時間可能有點冗長...... – PhirePhly 2008-09-26 03:01:34

+0

甚至有答案是你自己的問題按鈕。 – 2013-08-24 20:05:28

4

使用-s選項:

gcc -S program.c 
13

如果你想看取決於輸出的鏈接,那麼除了前面提到的gcc -S之外,輸出對象文件/可執行文件上的objdump也可能是有用的。這裏是由羅蘭梅里特一個非常有用的腳本,默認objdump的語法轉換成更具可讀性NASM語法:

#!/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; 

我懷疑這也可以在GCC-S的輸出使用。

+1

不過,這個腳本是一個骯髒的黑客,它不完全轉換語法。例如。 `mov eax,ds:0x804b794`不是很NASMish。另外,它有時只是去除有用的信息:`movzx eax,[edx + 0x1]`讓讀者猜測內存操作數是'byte'還是'word'。 – Ruslan 2017-10-07 22:00:01

+0

要首先在NASM語法中進行反彙編,請使用[Agner Fog's`objconv`](http://agner.org/optimize/#objconv)。你可以通過輸出file =`/ dev/stdout`將它反彙編到標準輸出中,這樣你就可以輸入`less`來查看。還有`ndisasm`,但它只是分解平面二進制文件,並不知道目標文件(ELF/PE)。 – 2017-10-07 22:12:51

7

大家都指出,使用GCC的-S選項。我還想補充一點,根據是否添加優化選項(none爲-O0,積極優化爲-O2),結果可能會有所不同(瘋狂!)。

特別是在RISC體系結構中,編譯器經常會在進行優化時將代碼轉換成幾乎無法識別的地方。看看結果令人印象深刻,令人着迷!

143

這將生成帶有C代碼+行號交織的asm,從而更容易地看到哪些行會生成哪些代碼。

# 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 

Algorithms for programmers發現,第4頁。

6

正如前面提到的,看看-S標誌。

也值得一看'-fdump-tree'系列的標誌,尤其是'-fdump-tree-all',它可以讓你看到一些gcc的中間形式。這些通常比彙編更具可讀性(至少對我來說),並讓您看到優化傳遞是如何執行的。

1

使用「-S」作爲選項。它顯示終端中的組件輸出。

6

如果您正在尋找LLVM彙編:

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

好了,大家都表示,使用-s選項。 如果使用-save-temps選項,還可以獲取預處理文件(.i),程序集文件(。)和目標文件(* .o)。 (通過使用-E,-S和-C得到它們。)

38

下面的命令行是從Christian Garbin's blog

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

我跑G ++從在Win-XP DOS窗口,針對包含隱式轉換

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' 

輸出asssembled生成的代碼iterspersed與原來的C++代碼例程(C++代碼被示爲所產生的ASM流中評論)

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) 
0

Output of these commnads

下面是看/打印任何C程序的彙編代碼上的Windows

控制檯/終端/命令提示的步驟:

  1. 寫類似的代碼塊一個C代碼編輯器,一個C程序,並用一種​​推廣保存它的.c

  2. 編譯並運行它。

  3. 一旦成功運行,進入文件夾,您安裝GCC編譯器和給

    下面的命令來獲得「.C」文件

    ℃的「.S」文件: \ GCC> GCC -S C文件的完整路徑ENTER

    一個實例命令(如在我的情況)

    C:\ GCC> GCC -SD:\ Aa_C_Certified \ alternate_letters.c

    此輸出原始 '.C' 的 '.S' 文件文件

4。在此之後,輸入以下命令

℃; \ GCC> CPP filename.s ENTER

示例命令(如在我的情況)

℃; \ GCC> CPP alternate_letters.s

這將打印/輸出C程序的整個彙編語言代碼。

相關問題