使用带参数的函数在堆栈中的 ebp 和 esp 行为 [英] Behaviour of ebp and esp in stacks using function with parameter

查看:30
本文介绍了使用带参数的函数在堆栈中的 ebp 和 esp 行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想了解有关堆栈的更多信息.特别是当调用带有参数的函数时会发生什么.为此,我编写了以下代码:

i want to learn more about stack. Especially, what happens when a function with parameter are called. For this, i write the following code:

    #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 函数的部分,因为首先我想了解这一部分):

and I get the following Assembly-Code(I will only add the part of the main function, because first I want to understand this section):

    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] 一样在同一个地方,对吗?

So, for this part I draw a little sketch to for myself. Please take a look :) My question : Where is at that point my ebp? Because of line 2 of my assembler code, it must be at the same place like [esp], right ?

现在,我的第二个问题后面的 sum 函数部分.

Now, the part of sum function which follows to my second question.

所以这是它的汇编代码:

so here is the assembly-code of that:

    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].但是,它仍然被使用.我怎么能想到呢?

so, I had learned that we can find our parameters always in [eb+12] and [ebp+8]. (I skipped the third parameter because I want to keep it simple) So my question is now: If I assume that esp=ebp and I look at my sketch, then I see that there is nothing in [esp+12] or now [ebp+12]. But nevertheless, it is used. How can I imagine that?

有人可以帮助我吗?我读过很多论文,但似乎没有人勾勒出这些东西.因此,很难理解.

Can someone help me? I've read so many papers, but nobody seems to sketch these things. Because of that, it is very hard to understand that.

谢谢!

这是我的草图:

推荐答案

在第一个函数执行过程中,espebp只有在指令之后才有相同​​的值>mov ebp, esp.在 and esp 之后,-16esp 的最低 4 位(最低 nibble)归零,espebp 发散,除非 esp 的最低位已经为零.然后 sub esp, 32esp 中减去 32,这里 espebp 肯定会发散.

During the first function execution esp and ebp have the same value only immediately after the instruction mov ebp, esp. After that and esp, -16 zeroes the lowest 4 bits (the lowest nibble) of esp, and esp and ebp diverge, unless the lowest bits of esp were zeroes already. Then sub esp, 32 subtracts 32 from esp and here esp and ebp diverge for sure.

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.

那么关于你的第二个问题:

Then regarding your second question:

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)和内存的值.你也可以像我上面那样在头脑中调试代码,但如果你是汇编初学者,使用调试器通常会容易得多,而且不容易出错.

Don't assume esp == ebp. In this second function too esp and ebp diverge upon execution of the instruction sub esp,16. Learn to use a debugger, for example GDB and single-step through the code and follow the values of registers (especially esp) and memory after each instruction. You can also debug the code in your head as I did above, but if you are a beginner in assembly, using a debugger is usually a lot easier and a lot less error-prone.

这篇关于使用带参数的函数在堆栈中的 ebp 和 esp 行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆