1.几个解释
esp:栈指针寄存器,内存放一指针,指向系统栈最上面一个栈帧栈顶。
ebp:基址指针寄存器,内存放一指针,指向系统栈最上面一栈帧的底部。
四个数据寄存器(eax,ebx,ecx,edx)
EAX :累加器(accumulator), 它是很多加法乘法指令的缺省寄存器。
EBX :"基地址"(base)寄存器, 在内存寻址时存放基地址。
ECX :计数器(counter), 是重复(REP)前缀指令和LOOP指令的内定计数器。
EDX: 则总是被用来放整数除法产生的余数。
mov :移内存的值。
dword:表示大小为四个字节
2.函数调用堆栈的过程
#include<stdio.h>
int sum(int a,int b)
{
int tmp=0;
tmp=a+b;
return tmp;
}
int main()
{
int x=2;
int y=5;
int ret=sum(x,y);
printf("%d",ret);
return 0;
}
程序汇编代码如图
main函数
则整个调用过程如下:
注意:
【1】main函数调用完sum,需要回到main函数
回来后继续从调用sum的下一行指令执行。
【2】主调函数中压实参的过程即给被调函数的形参开辟内存。
【3】main中call指令
call sum
add esp,8
指令跳转到sum函数之前得把下一行指令的地址压入到主调函数中,执行完被调函数,知道自己该回哪。
【4】被调函数在第一行所做的事情:
push ebp;
mov ebp,esp;
sub esp,4ch;
(1)把调用方函数的地址记录到当前函数的内存。
(2)把ebp指针从调用方函数栈底拉到当前函数栈底。
(3)给当前函数开辟内存,从esp到ebp,对栈帧进行初始化。
【5】return temp;
所对应的汇编代码
mov eax,dword ptr[ebp-4] //未产生临时量,通过eax把返回值带出来
mov esp,ebp
tpop ebp //把ebp值给esp,把esp拉到栈底,回退栈帧
【6】main中部分汇编指令
add esp,8
出栈 回退形参变量所占的内存(由主调方开辟,由主调方回辟)。
【7】函数的运行需要在栈上开辟内存,对栈内存的访问通过ebp指针偏移来进行访问。
3.函数的返回值通过什么带出来?
<=4字节 未产生临时量
>4 <=8字节 eax/[ebx] [edx]
>8字节 产生临时量,不用寄存器
下图为返回值>8字节函数调用堆栈过程
【1】临时量何时产生?
在进入调用函数之前,在主调函数中产生临时量。
【2】被调函数通过ebp+8获得main函数临时量的地址,将临时量内存写了。