long getesp() { __asm__("movl %esp,%eax"); } void main() { printf("%08X\n",getesp()+4); }
为什么esp在设置堆栈帧之前指向值,它是否与下面的代码有任何区别?
void main() { __asm__("movl %esp,%eax"); }
答案 0 :(得分:3)
我做了gcc -S file.c
getesp:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
#APP
# 4 "xxt.c" 1
movl %esp,%eax
# 0 "" 2
#NO_APP
leave
ret
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $20, %esp
call getesp
addl $4, %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf
addl $20, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
getesp
有一个pushl
来操纵esp
,并使用内联和{{1}获取esp
中eax
的操纵ebp
}}
进行函数调用以获取堆栈指针并将其放入main
内部肯定是不同的,它相差12个字节(在这种特定情况下)。这是因为当你执行call
推送eip
(如果不是段落,并且对于linux / unix正常程序执行它只是eip
)(需要引用),接下来是{ {1}}函数还有另一个带有getesp
的{{1}},然后将堆栈指针减去4.因为push
和ebp
是4个字节,所以总差异现在是12个字节。实际上我们可以在函数调用版本中看到。
如果没有函数调用,则不会推动eip
和其他ebp
操作,因此我们会在主要设置之后获得eip
值。
我对AT& T不满意所以这里的英特尔语法代码相同,下面是Intex语法asm转储。请注意,在esp
调用esp
内部主要值进入printf
时,没有推送或其他__asm__
修改,因此,主要内部的a
获取由esp
行在main中设置的__asm__
值。我们通过调用esp
得到的值是(你期望的) - 12,如上所述。
C代码
sub esp, 20
输出在我的情况下是针对特定的运行:
getesp
intel语法转储是:
#include <stdio.h>
int a;
long getesp() {
__asm__("mov a, esp");
}
int main(void)
{
__asm__("mov a,esp");
printf("%08X\n",a);
getesp ();
printf("%08X\n",a);
}
我希望这会有所帮助。