2013-12-20 53 views
1

函數的堆棧中ebp和esp的行爲我想了解有關堆棧的更多信息。特別是,當調用帶參數的函數時會發生什麼。對於這一點,我寫了下面的代碼:使用帶參數

#include <stdio.h> 
    int sum(int d, int e, int f){ 
     int result = d + e + f; 
     return result; 
    } 

    int main(void){ 
    int a = 5; 
    int b = 4; 
    int c = 2; 

    int erg = sum(a,b,c); 
    printf("Result is: %d", erg); 

    } 

,我得到以下彙編代碼(我只加main功能的一部分,因爲首先我想了解這部分):

push ebp, 
    mov ebp, esp 
    and esp, -16 
    sub esp, 32 
    mov DWORD PTR[esp+28], 5 
    mov DWORD PTR[esp+24], 4 
    mov DWORD PTR[esp+20], 2 
    mov eax, DWORD PTR[esp+20] 
    mov DWORD PTR[esp+8], eax 
    mov eax, DWORD PTR[esp+24] 
    mov DWORTD PTR[esp+4], eax 
    mov eax, DWORD PTR[esp+28] 
    mov DWORD PTR[esp], eax 
    call sum 
    ........ 
    ........ 

因此,對於這部分我爲自己畫了一個小圖。請看看:) 我的問題:在哪裏我的ebp?由於我的彙編代碼的第2行,它必須在[esp]的相同位置,對吧?

現在,我的第二個問題的部分和函數。

所以這裏的是彙編代碼:

push ebp 
    mov ebp, esp 
    sub esp, 16 
    mov eax, DWORD PTR[ebp+12] 
    mov edx, DWORD PTR[ebp+8] 
    mov edx, eax 
    ------------ 

所以,我已經瞭解到,我們總能找到在[eb+12][ebp+8]我們的參數。 (我跳過了第三個參數,因爲我想保持簡單) 所以我的問題是現在: 如果我假設esp = ebp,我看我的草圖,然後我看到沒有什麼[esp+12]或現在[ebp+12]。但是,它被使用。 我怎麼想象?

有人可以幫助我嗎?我讀過很多論文,但似乎沒有人勾畫這些東西。因此,這很難理解。

謝謝!

這裏是我的草圖:

enter image description here

回答

4

在第一功能執行espebp指令mov ebp, esp後具有相同的價值只有馬上。在那之後,除非esp的最低位已經爲零,否則espespebp的最低4位(最低半位元組)爲零。然後sub esp, 32esp減去32,這裏espebp肯定是分歧的。

push ebp     ; esp = esp - 4; [esp] = ebp. 
mov ebp, esp    ; ebp = esp. create the stack frame. 
and esp, -16    ; make lowest 4 bits of esp zeros, for alignment. 
sub esp, 32    ; esp = esp - 32. make space for local variables. 
mov DWORD PTR[esp+28], 5 ; a = 5 
mov DWORD PTR[esp+24], 4 ; b = 4 
mov DWORD PTR[esp+20], 2 ; c = 2 
mov eax, DWORD PTR[esp+20] ; eax = c (eax = 2) 
mov DWORD PTR[esp+8], eax ; [esp+8] = dword 2 
mov eax, DWORD PTR[esp+24] ; eax = b (eax = 4) 
mov DWORTD PTR[esp+4], eax ; [esp+4] = dword 4 
mov eax, DWORD PTR[esp+28] ; eax = a (eax = 5) 
mov DWORD PTR[esp], eax ; [esp] = dword 5 
call sum     ; the above lines define the parameters for the 
          ; function sum, that is called now. 

那麼關於你的第二個問題:

push ebp     ; esp = esp - 4; [esp] = ebp. 
mov ebp, esp    ; ebp = esp. 
sub esp, 16    ; esp = esp - 16. create space for local variables. 
          ; at this point: 
          ; [ebp] == old value of ebp. 
          ; [ebp+4] == return address pushed by call, 
          ;    to be used by the next ret. 
          ; [ebp+8] == dword 5 (a) 
          ; [ebp+12] == dword 4 (b) 
          ; [ebp+16] == dword 2 (c) 
mov eax, DWORD PTR[ebp+12] ; eax = 4 
mov edx, DWORD PTR[ebp+8] ; edx = 5. gets overwritten by the next instruction.   
mov edx, eax    ; edx = eax = 4 

不要以爲esp == ebp。在這個第二個功能espebp也執行sub esp,16指令時發散。學習使用調試器(例如GDB),並單步執行代碼,並在每條指令之後遵循寄存器(特別是esp)和內存的值。你也可以像上面那樣調試你的頭腦中的代碼,但是如果你是一個初學者,使用調試器通常要容易得多,而且容易出錯。