Assembly 设置后帧指针指向何处?
尽管我看教科书试图理解这一点,但我还是有困难Assembly 设置后帧指针指向何处?,assembly,stack,x86,Assembly,Stack,X86,尽管我看教科书试图理解这一点,但我还是有困难 0x08048b29 <func+0>: push %ebp 0x08048b2a <func+1>: mov %esp,%ebp 0x08048b2c <func+3>: push %ebx ... 0x08048b30 <phase_2+7>: lea -0x28(%ebp),%eax 0x08048b29:推送%ebp 0x08048b
0x08048b29 <func+0>: push %ebp
0x08048b2a <func+1>: mov %esp,%ebp
0x08048b2c <func+3>: push %ebx
...
0x08048b30 <phase_2+7>: lea -0x28(%ebp),%eax
0x08048b29:推送%ebp
0x08048b2a:mov%esp,%ebp
0x08048b2c:推送%ebx
...
0x08048b30:lea-0x28(%ebp),%eax
在lea指令中,我了解到%eax在%ebp之前的0x28处获取值,但这到底是在哪里?它是0x8048b29-0x28(函数开始前的0x28)还是什么?ebp寄存器通常用于函数中访问传递给函数的任何参数。在调用此函数之前,寄存器未传递的任何参数都会推送到堆栈上。此函数开始时,将保存调用函数的基指针 (1)
0x08048b29:推送%ebp
堆栈的新顶部被复制到ebp中,用作此函数中的基指针
(2) 0x08048b2a:mov%esp%ebp
最后,保存ebx,它很可能是传递给寄存器中函数的变量
(3) 0x08048b2c:推送%ebx
在所有这些函数输入代码之后,ebp寄存器指向堆栈的中间。在堆栈的上面(朝向最新推送的项目)是在上面#3中推送的ebx值。在堆栈的下面是调用函数的旧ebp(保存在上面的#1中),最重要的是。。。通过堆栈传递到此函数的任何参数(在调用函数之前完成)
(4) lea-0x28(%ebp),%eax
最后一条指令引用堆栈传递的其中一个参数。ebp最终指向堆栈,而不是任何函数代码地址。这对于ebp是很正常的,它最常用作堆栈指针。从调用该函数的上下文来看。执行此操作的代码如下所示:
caller+...: push argN
caller+...: ...
caller+...: push arg0
caller+...: call func
[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()
i、 e.参数按如下顺序放置在堆栈上:在进入func()
时,堆栈将具有以下布局:
[esp+(N*4)] : argN
... : arg(N-1)...arg2
[esp+4 ] : arg1
[esp ] : <return address to caller()+...>
然后,代码继续在堆栈上推送几个寄存器,因为每次%esp
被-4更改时,寄存器会向下增长。最终(您在反汇编中没有显示,但它会出现)您将有一条指令subl$…,%esp
。这就是为局部变量分配空间的原因。最终的堆栈布局类似于:
caller+...: push argN
caller+...: ...
caller+...: push arg0
caller+...: call func
[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()
[ebp+4+(N*4)][]:argN
... : arg(N-1)…arg2
[ebp+8][]:arg1
[ebp+4][]:
[ebp][]:
[ebp-4][]:
[ebp-8][]:。。。
... : 局部变量区域
[ebp-??][esp]:func()的堆栈结束
[esp…ebp-4]
之间的任何地址都在函数的堆栈框架内,它包含代表调用方保存的寄存器(如ebx
在您显示的反汇编中)或局部变量
因此,当您在代码中看到对
%ebp-XX
的任何访问时,它是在局部变量空间中,如果您看到%ebp+YY
它是在包含函数参数的空间中。它们这样做的原因是,参数总是可以被相同的ebp偏移引用。您不能将esp用于此目的,因为此函数可能需要将堆栈指针用于临时push/pop指令。