gpt4 book ai didi

assembly - 使用带参数的函数在堆栈中的 ebp 和 esp 行为

转载 作者:行者123 更新时间:2023-12-02 04:41:47 27 4
gpt4 key购买 nike

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

    #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] 相同的位置,对吗?

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

所以这是它的汇编代码:

    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

最佳答案

在第一个函数执行期间,espebp 只有在指令 mov ebp, esp 之后才具有相同的值。之后and esp, -16esp的最低4位(最低半字节)归零,espebp 发散,除非 esp 的最低位已经为零。然后 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)和内存的值。您也可以像我上面那样在头脑中调试代码,但如果您是汇编初学者,使用调试器通常会容易得多,而且不容易出错。

关于assembly - 使用带参数的函数在堆栈中的 ebp 和 esp 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20695203/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com