脚本宝典收集整理的这篇文章主要介绍了C语言函数调用堆栈过程,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
函数调用堆栈过程
调用约定
函数的调用约定很多,常见的包括__stdcall,__cdecl,__fastcall,__thiscall等等。
主要的区别在于约束的三个事件,一个是参数传递是从左开始呢还是从右开始,还有就是堆栈清理的清理方是调用者还是被调用者。另外来说不同的函数调用约定函数产生的符号名称不同。
举个栗子,对于cdecl,参数是从右到左传递,堆栈平衡是由调用函数来执行的;而win32API一般使用的是stdcall,参数同样是采用了从右往左传递,而函数的堆栈平衡则是由被调用函数执行(不支持可变参数);fastcall参数直接放入寄存器而非栈中,规定前两个参数分别放入ecx和edx中,当寄存器用完时候参数才按照从右往左的顺序压入堆栈。
调用约定
使用场景
_cdecl
c调用约定
_stdcall
windows标准调用约定
_fastcall
快速调用约定
_thiscall
C++成员函数调用约定
压栈过程
int add(int a, int b)
{
return a+b;
}
int main()
{
int a = 1;
int b = 2;
int res = add(a,b);
return 0;
}
- 首先从main函数初始,ebp和esp分别存放函数的栈底地址和栈顶地址,此时ebp-4即是a,ebp-8则是b的地址。
- 然后调用函数add,第一先将参数从右往左依次入栈,push在调用方的函数栈当中,也就是说此时esp往里开辟了两个参数
- 执行call指令,首先将下一条指令地址进行入栈,
@H_591_126@
-
随后开辟新栈,进行现场保护
- 这里省略了现场保护的过程,主要做的就是push了多个寄存器(例如edi,ebx,edi)的值,在完成后还原现场进行pop,对程序没有什么其他影响这里省略。
- 将edi置为栈顶地址,ecx置为11h,eax置为0CCCCCCCCh。
- 从edi开始循环拷贝eax,也就是将整个栈内初始化为0CCCCCCCCh,也就是常见的“烫”。
- 执行add函数
开辟一个临时变量,值是(a)(ebp+8) + (b)(ebp+0Ch),将这个值放入eax中。
-
执行完成后回退栈针
那么再来看看其他情况
上面的返回值是一个int类型,也就是C的内置类型,通过eax寄存器带出。
如果是一个double或者long long呢?那么可以通过eax、edx两个寄存器带出。
如果是一个自定义类型呢?其实也是类似的:
以上是脚本宝典为你收集整理的C语言函数调用堆栈过程全部内容,希望文章能够帮你解决C语言函数调用堆栈过程所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。