2013-02-22 50 views
0

我已通過以下一系列文章讀拆卸線:http://www.altdevblogaday.com/2011/11/09/a-low-level-curriculum-for-c-and-cOSX 64位C++通過線

所示的反彙編代碼和反彙編代碼我管理,以產生同時運行相同的代碼變化相當顯著和我缺乏解釋差異的理解。

有沒有人可以逐行瀏覽它,也許可以解釋它在每個步驟中做了什麼?我從周圍搜索中得到了感覺,我已經完成了前幾行與幀指針有關的事情,在我的反彙編代碼中似乎還有一些額外的行,以確保在將新值寫入它們之前寄存器是空的(缺席從文章中的代碼)

我在OSX(原作者使用Windows)上使用g ++編譯器從XCode 4中運行此操作。我真的無法知道這些差異是由於操作系統,體系結構(32位還是64位可能?)或編譯器本身。它甚至可能是我猜的代碼 - 我的代碼被包裝在主函數聲明中,而原始代碼沒有提到這一點。

我的代碼:

int main(int argc, const char * argv[]) 
{ 

    int x = 1; 
    int y = 2; 
    int z = 0; 

    z = x + y; 

} 

我的反彙編代碼:

0x100000f40: pushq %rbp 
0x100000f41: movq %rsp, %rbp 
0x100000f44: movl $0, %eax 
0x100000f49: movl %edi, -4(%rbp) 
0x100000f4c: movq %rsi, -16(%rbp) 
0x100000f50: movl $1, -20(%rbp) 
0x100000f57: movl $2, -24(%rbp) 
0x100000f5e: movl $0, -28(%rbp) 
0x100000f65: movl -20(%rbp), %edi 
0x100000f68: addl -24(%rbp), %edi 
0x100000f6b: movl %edi, -28(%rbp) 
0x100000f6e: popq %rbp 
0x100000f6f: ret  

從原來的文章的反彙編代碼:

mov dword ptr [ebp-8],1 
mov dword ptr [ebp-14h],2 
mov dword ptr [ebp-20h],0 
mov eax, dword ptr [ebp-8] 
add eax, dword ptr [ebp-14h] 
mov dword ptr [ebp-20h],eax 

通過在線故障提供全系列將是非常有啓發但任何幫助理解這一點,將不勝感激。

回答

0

你反彙編的代碼和文章的代碼有兩個主要的區別。

其中之一是該文章使用英特爾彙編語法,而您的反彙編代碼使用傳統的Unix/AT彙編語法。兩者之間的一些差異記錄在Wikipedia

另一個區別是本文忽略了設置堆棧幀的函數序言和函數epilogue,它破壞了堆棧幀並返回給調用者。他正在分解的程序必須包含執行這些操作的指令,但他的反彙編程序沒有顯示它們。 (其實堆棧幀可如果優化已啓用,可能會被忽略,但它顯然不是啓用。)

也有一些細微的差別:你的代碼是使用局部變量稍有不同的佈局,你的代碼是在不同的寄存器中計算總和。

在Mac上,G ++不支持英特爾的發光助記符,但鐺做:

:; clang -S -mllvm --x86-asm-syntax=intel t.c 
:; cat t.s 
    .section __TEXT,__text,regular,pure_instructions 
    .globl _main 
    .align 4, 0x90 
_main:         ## @main 
    .cfi_startproc 
## BB#0: 
    push RBP 
Ltmp2: 
    .cfi_def_cfa_offset 16 
Ltmp3: 
    .cfi_offset rbp, -16 
    mov RBP, RSP 
Ltmp4: 
    .cfi_def_cfa_register rbp 
    mov EAX, 0 
    mov DWORD PTR [RBP - 4], EDI 
    mov QWORD PTR [RBP - 16], RSI 
    mov DWORD PTR [RBP - 20], 1 
    mov DWORD PTR [RBP - 24], 2 
    mov DWORD PTR [RBP - 28], 0 
    mov EDI, DWORD PTR [RBP - 20] 
    add EDI, DWORD PTR [RBP - 24] 
    mov DWORD PTR [RBP - 28], EDI 
    pop RBP 
    ret 
    .cfi_endproc 


.subsections_via_symbols 

如果添加-g標誌,編譯器將添加調試信息包括源文件名和行號。整體來說這太大了,但這是相關的部分:

.loc 1 4 14 prologue_end  ## t.c:4:14 
Ltmp5: 
    mov DWORD PTR [RBP - 20], 1 
    .loc 1 5 14     ## t.c:5:14 
    mov DWORD PTR [RBP - 24], 2 
    .loc 1 6 14     ## t.c:6:14 
    mov DWORD PTR [RBP - 28], 0 
    .loc 1 8 5     ## t.c:8:5 
    mov EDI, DWORD PTR [RBP - 20] 
    add EDI, DWORD PTR [RBP - 24] 
    mov DWORD PTR [RBP - 28], EDI 
2

原始文章中的所有代碼都在您的代碼中,只是有一些額外的東西。這個:

0x100000f50: movl $1, -20(%rbp) 
0x100000f57: movl $2, -24(%rbp) 
0x100000f5e: movl $0, -28(%rbp) 
0x100000f65: movl -20(%rbp), %edi 
0x100000f68: addl -24(%rbp), %edi 
0x100000f6b: movl %edi, -28(%rbp) 

直接對應於文章中提到的6條指令。

0

首先,列爲「來自原始文章」的彙編程序正在使用「Intel」語法,其中帖子中的「反彙編輸出」爲「AT & T語法」。這解釋了指令的參數順序是「回到前面」[我們不要爭論哪個是對還是錯,好嗎?],並且寄存器名稱以%爲前綴,常數以$爲前綴。在存儲器位置/偏移量與寄存器參考方面也有所不同 - 英特爾彙編器中的dword ptr [reg+offs]轉換爲l作爲指令後綴,offs(%reg)轉換爲l

32位與64位重命名一些寄存器 - %rbp與文章代碼中的ebp相同。

實際偏移量(如-20)是不同的,部分原因是寄存器是64位的大,但也因爲你有argcargv作爲您的函數參數,存儲作爲函數的開始部分的一部分 - 我有一種感覺,原始文章實際上是拆開與main不同的功能。

+0

謝謝你 - 絕對清除了一些我不明白的東西!事實上,這是一個不同的語法,完全解釋了許多以及你對不同偏移的看法。 – GeoffK 2013-02-22 22:43:12

+0

原文似乎很好。在x86上,'argc'和'argv'將被調用者推送,因此相對於'ebp'處於* positive *偏移量(ebp + 0是舊BP,ebp + 4是返回地址,ebp + 8是第一個參數...)。在x86_64 OSX上,前兩個參數傳入'rdi'(在這種情況下是'edi',因爲它是一個int)和'rsi'。它看起來像是用'-O0'編譯的,所以參數會立即保存到堆棧中。 – 2013-02-22 23:03:02

+0

對此不以爲然 - 但我如何啓用這些優化?肯定會喜歡用/不用,並且比較 – GeoffK 2013-02-22 23:05:56