源码:
void bar(int j, int k); // a function to call
void demo_stackframe(int a, int b, int c) {
int x;
char buffer[64];
int y;
int z;
// body of function not terribly relevant other than
bar(z, y);
}
**基于ESP 的栈帧**
** 基于EBP 的栈帧** CALL 函数调用指令
格式: CALL OPRD
功能: 过程调用指令
1. 其中OPRD为过程的目的地址.
2. 过程调用可分为段内调用和段间调用两种.寻址方式也
可以分为直接寻址和间接寻址两种.
3. 本指令不影响标志位.
近调用 - 调用当前代码段(CS 寄存器当前指向的段)中的过程,有时称为段内调用。
执行近调用时,处理器将 EIP 寄存器的值(包含 CALL 指令后面的指令的偏移量)压入堆栈(稍后用作
返回指令指针)。然后,处理器分支到当前代码段中由目标操作数指定的地址。目标操作数指定代码段中的绝对偏移量
(即相对于代码段基址的偏移量)或相对偏移量(相对于 EIP 寄存器中指令指针的当前值的有符号位移量,此指针指向
CALL 指令后面的指令)。执行近调用时,CS 寄存器保持不变。
对于近调用,绝对偏移量在通用寄存器或内存位置(r/m16 或 r/m32)中间接指定。操作数大小属性确
定目标操作数的大小(16 位或 32 位)。绝对偏移量直接加载到 EIP 寄存器。如果操作数大小属性是 16,
则 EIP 寄存器的两个高位字节清除为零,得到大小最大为 16 位的指令指针。(使用堆栈指针 [ESP] 作为基址
寄存器来间接访问绝对偏移量时,使用的基址值是 ESP 在指令执行之前的值)。
在汇编代码中,相对偏移量(rel16 或 rel32)通常指定为标签,但是在机器代码级别,它的编码形式
是有符号的 16 位或 32 位立即数。此值会加到 EIP 寄存器中的值上。对于绝对偏移量,操作数大小属性确定
目标操作数的大小(16 位或 32 位)
push ip,jmp xxx;
远调用 - 调用当前代码段之外的段中的过程,有时称为段间调用。
push CS,push ip,jmp xxx;
RET 返回指令 参数与 return 不同
功能: 当调用的过程结束后实现从过程返回至原调用程序的下一条指令,
本指令不影响标志位.
RET指令用栈中的数据修改IP的内容 实现近转移
IP=SS*16+SP
SP=SP+2 相当于pop IP,jmp ip
RET指令用栈中的数据修改CS和IP的内容 实现远转移
IP=SS*16+SP
SP=SP+2
CS=SS*16+SP
SP=SP+2
相当于pop IP,pop CS,jmp cs:ip
RET指令可以带有一个立即数i16 则堆栈指针SP将增加
ret 08
pop ip
add sp,08
jmp ip
**进入函数前**