esp ebp eip 函数压栈

intel cpu的程序,关于函数调用压栈的过程,到底如何实现的? ESP,EBP,EIP都负责什么任务?

我们现在要调用函数A, 有三个参数,a,b,c.。执行A函数,需要两部,第一步, 在进入函数之前,要将c,b,a依次压入栈中,然后进入到函数A中。第二步,开始执行程序。

第一步具体的细节为:

mov c  0xC(esp)

mov b 0x8(esp)

mov a 0x4(esp)

call A
(esp)代表堆栈寄存器esp所指向的内存地址。oxc(esp)代表了(esp所指向的内存地址+0xC)的地址。

执行call A指令时,会将EIP(下一步要执行的指令的地址)存入堆栈中,即好比执行了mov EIP (esp).

第二步的细节为:

push ebp

mov esp ebp

..........

pop ebp

ret
第二步中,push ebp和mov esp ebp不是A函数中要处理的逻辑,是为了函数调用而实现的,任何一个函数调用都会有这两步。   ,.....代表函数A中的一些处理分为几种情况:

            (1) 如果要使用函数A的参数,则使用ebp+offset来获得;

             (2) 如果要进行函数调用,则像第一步一样;

             (3) 如果要使用栈stack, 则使用esp堆栈指针。但是在第二步的ret之前,要将esp恢复到原值。

intel中关于call操作的解释为,先将esp的值改变,然后压入栈中:

ELSE IF StackAddrSize = 32
THEN
IF OperandSize = 32
THEN
ESP ← (ESP − 4);
IF (SRC is FS or GS)
THEN
TEMP = ZeroExtend32(SR
ELSE IF (SRC is IMMEDIATE) 
TEMP = SignExtend32(SRC
ELSE
TEMP = SRC;
FI;
SS:ESP ← TEMP; (* Push doublewor
ELSE (* OperandSize = 16*)
ESP ← (ESP − 2);
SS:ESP ← SRC; (* Push word *)

可以看到,第二步完成之后,ebp和esp的值都没有改变。

在进行第二步时,刚进入第二步,执行了push ebp和mov esp ebp, 但是还没有执行A自己代码时,(esp)的值为执行完A后要执行的代码的地址EIP的值。0x4(esp)的值为参数a, 0x8(esp)为参数b,0xc(esp)为参数c.

总结:
我写这篇文章所用的编译器为GCC, Intel x86平台。希望对于esp, ebp,eip作用和函数调用如何实现比较困惑的朋友有所帮助。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值