2013-08-25 126 views
1

我想了解以下函數的反彙編代碼。C函數的反彙編

void func(char *string) { 
    printf("the string is %s\n",string); 
} 

反彙編代碼如下。

1) 0x080483e4 <+0>:  push %ebp 
2) 0x080483e5 <+1>:  mov %esp,%ebp 
3) 0x080483e7 <+3>:  sub $0x18,%esp 
4) 0x080483ea <+6>:  mov $0x80484f0,%eax 
5) 0x080483ef <+11>: mov 0x8(%ebp),%edx 
6) 0x080483f2 <+14>: mov %edx,0x4(%esp) 
7) 0x080483f6 <+18>: mov %eax,(%esp) 
8) 0x080483f9 <+21>: call 0x8048300 <[email protected]> 

有人能告訴我第4-7行是什麼意思(不是字面解釋)。還有爲什麼24字節分配在第3行的堆棧上?

+0

您是否熟悉堆疊的工作原理,例如當使用'push' /'pop'時? – DCoder

+0

我想我知道 – user146297

+4

然後這些線是相當簡單的 - 而不是'push'ing一個值壓入堆棧,GCC手動移動堆棧指針和感動,值到堆棧的新的頂部。看看[本文]的「參數」部分(http://codearcana.com/posts/2013/05/21/a-brief-introduction-to-x86-calling-conventions.html),它在一些更多的細節。至於「爲什麼24字節的堆棧」,這是編譯器的內部決定,它可能與*堆棧對齊*,*堆棧金絲雀*或只是一個隨機決定有關。 – DCoder

回答

5

基本上就是發生在這裏:

4) 0x080483ea <+6> : mov $0x80484f0,%eax 

負荷"the string is %s\n"地址爲eax

5) 0x080483ef <+11>: mov 0x8(%ebp),%edx 

移動的說法stringedx

6) 0x080483f2 <+14>: mov %edx,0x4(%esp) 

推送的edxstring值進棧,printf

7) 0x080483f6 <+18>: mov %eax,(%esp) 

推的第二個參數的eax"the string is %s\n"值入堆棧中,printf第一個參數,然後它將調用printf

sub $0x18,%esp是沒有必要的,因爲函數沒有局部變量,GCC似乎很喜歡做額外的空間,但老實說,我不知道爲什麼。

+0

謝謝你的回答。參數字符串表示字符串的地址?同樣關於(sub $ 0x18,%esp),我認爲你是正確的,因爲使用printf的任意no函數反彙編不同的函數表明printf不會影響堆棧中保留的變量no。或者它可能與@Dcoder指出的堆棧金絲雀有關 – user146297

+0

@ user146297至於字符串,是的,字符串的地址。不必要的'sub XXX,%esp'這種行爲一直困擾着我很久,我找不到答案。 – 2013-08-25 11:59:59

+1

沒有這個子,'mov%edx,0x4(%esp)'會破壞堆棧。 –

1

堆棧是連續的存儲器區域開始於較高的地址和在esp結束。每當你需要你的堆棧增長時,你從esp減去。每個函數都可以在堆棧中有一個框架。這是功能擁有的堆棧的一部分,並在完成後負責清理。這意味着,當功能啓動時,它會減少esp以創建其框架。當它結束時,它將增加它。 ebp通常指向您的框架的開始。

最初,該函數將ebp推送到該棧,以便函數結束時可以存儲它,設置esp = ebp以標記幀的開始並分配28個字節。爲什麼28?爲了對齊。它已經爲ebp分配了4個字節。 4 + 28 = 32。

的線4-7將準備調用printf。它期望它的論據在調用者的框架中。當我們讀取mov 0x8(%ebp), %edx時,我們從調用者的框架中取出我們的參數char* stringprintf也會這樣做。

請注意,您的程序集缺少leaveret指令來清除堆棧並返回給調用者。