2016-10-07 140 views
0
aduna2: 

.LFB0: 
.cfi_startproc 
    push ebp 
.cfi_def_cfa_offset 8 
.cfi_offset 5, -8 
    mov ebp, esp 
.cfi_def_cfa_register 5 
    sub esp, 16 
    mov DWORD PTR [ebp-4], 10 
    mov eax, DWORD PTR [ebp+12] 
    mov edx, DWORD PTR [ebp+8] 
    add edx, eax 
    mov eax, DWORD PTR [ebp+16] 
    add edx, eax 
    mov eax, DWORD PTR [ebp-4] 
    add eax, edx 
    leave 

aduna: 

.LFB1: 
.cfi_startproc 
    push ebp 
.cfi_def_cfa_offset 8 
.cfi_offset 5, -8 
    mov ebp, esp 
.cfi_def_cfa_register 5 
    sub esp, 28 
    mov DWORD PTR [ebp-4], 7 
    mov eax, DWORD PTR [ebp-4] 
    mov DWORD PTR [esp+8], eax 
    mov eax, DWORD PTR [ebp+12] 
    mov DWORD PTR [esp+4], eax 
    mov eax, DWORD PTR [ebp+8] 
    mov DWORD PTR [esp], eax 
    call aduna2 
    leave 

main: 

.LFB2: 
.cfi_startproc 
    push ebp 
.cfi_def_cfa_offset 8 
.cfi_offset 5, -8 
    mov ebp, esp 
.cfi_def_cfa_register 5 
    and esp, -16 
    sub esp, 16 
    mov DWORD PTR [esp+4], 6 
    mov DWORD PTR [esp], 5 
    call aduna 
    mov DWORD PTR [esp+4], eax 
    mov DWORD PTR [esp], OFFSET FLAT:.LC0 
    call printf 
    leave 

我在這段代碼中有以下問題:在主要我無法弄清楚當esp 16相對於ebp。我在「adunare」和「adunare2」中遇到了這個問題。我無法弄清楚它會在ebp的相對位置。我無法弄清楚爲這個程序繪製一個堆棧,因爲我所有的堆棧在「adunare2」我得到了ebp + 8,ebp + 12,ebp + 16.這將有助於向我展示一個,因爲我不明白髮生了什麼。在每次通話時都會插入一個返回地址?如果在「adunare2」中是這樣,你如何使用+ 8,+ 12,+ 16得到提到的參數?彙編堆棧3函數

這裏是C代碼:

#include<stdio.h> 

int aduna2(int a,int b,int c) 
{ 
    int d=10; 
    return a+b+c+d; 
} 

int aduna(int a,int b) 
{ 
    int c=7; 
    return aduna2(a,b,c); 
} 

int main() 
{ 
    printf("%d\n",aduna(5,6)); 
} 
+0

反彙編看起來不完整。 (我希望在'離開'後'ret')。你怎麼得到的?這不是一些「聰明」的反彙編輸出嗎?使用編譯器列表或正常反彙編。 – Ped7g

回答

0

即使在不完全拆卸,我想我可以回答「什麼aduna之前做主要有棧」:

main: 
    ; store old ebp value into stack (to restore it before return) 
    push ebp 
    mov ebp, esp ; copy current value of esp to ebp 

在這一點上兩者ESP和ebp具有相同的值,指向當前棧頂,假設它是0x0054,那麼堆棧內存如下所示:

address | value 
----------------- 
0x0050 | ???? 
0x0054 | old_ebp   <- esp/ebp pointing here 
0x0058 | return address to "main" caller 
0x005C | whatever was already in stack before calling main 

則代碼繼續爲 「aduna」 功能準備參數:

and esp, -16  ; -16 = 0xFFFFFFF0 -> makes esp 16B aligned 
     ; esp here is 0x0050 
    sub esp, 16  ; make room at top of stack for 16B, esp = 0x0040 
     ; store the arguments into the stack 
    mov DWORD PTR [esp+4], 6 ; at 0x0044 goes value 6 
    mov DWORD PTR [esp], 5  ; at 0x0040 goes value 5 
    call aduna     ; call aduna 

現在進入aduna的EBP/ESP和堆棧內存之後看起來是這樣的:

ebp = still 0x0054, nothing did modify it 
esp = 0x003C (call did pust return address at top of stack) 

address | value 
----------------- 
0x0038 | ???? 
0x003C | return address to instruction after "call aduna" <- esp 
0x0040 | 5 
0x0044 | 6 
0x0048 | ???? 
0x004C | ???? 
0x0050 | ???? 
0x0054 | old_ebp   <- ebp pointing here 
0x0058 | return address to "main" caller 
0x005C | whatever was already in stack before calling main 

並在aduna開始與序幕碼push ebpmov ebp, esp,所以堆棧的頂部會改變一點:

address | value 
----------------- 
0x0038 | 0x0054 <- both esp and ebp pointing here (= 0x0038) 
0x003C | return address to instruction after "call aduna" 
0x0040 | 5 
0x0044 | 6 

因此,mov eax, DWORD PTR [ebp+12]將取地址0x0044(0x38 + 0x0C = 0x44),存儲的地址爲6. ebp+8指向5的值。其餘的esp/ebp組合位於aduna以下的點,放入局部變量中(居住在「堆棧」部分的內存),我不會描述,因爲一旦你理解了這個最初的部分,你應該能夠解釋它的其餘部分。

對於leave檢查指令集手冊(它確實改變了espebp)。而且缺失的ret也很重要,同樣也要更改esp