设置后帧指针指向何处?

时间:2010-10-14 21:47:15

标签: assembly stack ia-32

尽管看着教科书试图掌握这一点,但我遇到了麻烦。

    0x08048b29 <func+0>: push   %ebp
    0x08048b2a <func+1>: mov    %esp,%ebp
    0x08048b2c <func+3>: push   %ebx
    ...
    0x08048b30 <phase_2+7>: lea    -0x28(%ebp),%eax

在lea指令中,我理解%eax在%ebp之前得到的值为0x28,但究竟是哪里?它是0x8048b29 - 0x28(函数开头之前的0x28)还是什么?

2 个答案:

答案 0 :(得分:1)

ebp寄存器通常在函数中用于访问传递给函数的任何参数。在调用此函数之前,寄存器未传递的任何参数都会被压入堆栈。在此函数开始时,将保存调用函数的基指针。

(1)0x08048b29 <func+0>: push %ebp

将堆栈的新顶部复制到ebp中,作为此函数中的基指针。

(2)0x08048b2a <func+1>: mov %esp,%ebp

最后,保存了ebx,这可能是一个传递给寄存器中函数的变量。

(3)0x08048b2c <func+3>: push %ebx

在所有这个函数入口代码之后,ebp寄存器指向堆栈的中间位置。在堆栈上方(朝向最新的推送项目)是在上面#3中推送的ebx值。堆栈下面是来自调用函数的旧ebp(保存在上面的#1中),最重要的是......通过堆栈传递给该函数的任何参数(在调用函数之前完成)。

(4)lea -0x28(%ebp),%eax

最后一条指令指的是堆栈传递的其中一个参数。 ebp最终指向堆栈,而不是任何函数代码地址。这对于ebp来说非常正常,它通常用作指向堆栈的指针。

答案 1 :(得分:1)

调用该函数的上下文中查看此内容。这样做的代码看起来像:

caller+...: push argN
caller+...: ...
caller+...: push arg0
caller+...: call func

即。参数以这样的顺序放入堆栈中,在进入func()时,堆栈将具有以下布局:

[esp+(N*4)] : argN
...         : arg(N-1)...arg2
[esp+4    ] : arg1
[esp      ] : <return address to caller()+...>

然后执行push %ebp; mov %esp, %ebp序列,其中更改 %esp(按-4),以便您的布局现在为:

[ebp+4+(N*4)][esp+(N*4)] : argN
...                      : arg(N-1)...arg2
[ ebp+8     ][esp+8    ] : arg1
[ ebp+4     ][esp+4    ] : <return address to caller()+...>
[ ebp       ][esp      ] : <saved %ebp of caller>

然后代码继续在堆栈上再推几个寄存器 - 因为每次%esp改变为-4时,它都会向下增长。最终(你没有在你的反汇编中显示但它会在那里)你会得到一条指令subl $..., %esp。这是为您的局部变量分配空间的原因。最终的堆栈布局类似于:

[ebp+4+(N*4)][         ] : argN
...                      : arg(N-1)...arg2
[ ebp+8     ][         ] : arg1
[ ebp+4     ][         ] : <return address to caller()+...>
[ ebp       ][         ] : <saved %ebp of caller>
[ ebp-4     ][         ] : <saved %ebx of caller>
[ ebp-8     ][         ] : ...
...                      : region for local variables
[ ebp-??    ][ esp     ] : end of stack for func()

[esp ... ebp-4]之间的任何地址都在您的函数的堆栈框架内,并且它包含代表调用者保存的寄存器(如{1}显示的反汇编代码中的ebx )或局部变量。

因此,当您在代码中看到%ebp - XX在本地变量空间中的任何访问权时,如果您看到%ebp + YY它位于包含函数参数的空间内。