2016-10-07 112 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