C语言函数调用堆栈过程 | 您所在的位置:网站首页 › c语言的函数调用过程 › C语言函数调用堆栈过程 |
函数调用堆栈过程
调用约定
函数的调用约定很多,常见的包括__stdcall,__cdecl,__fastcall,__thiscall等等。主要的区别在于约束的三个事件,一个是参数传递是从左开始呢还是从右开始,还有就是堆栈清理的清理方是调用者还是被调用者。另外来说不同的函数调用约定函数产生的符号名称不同。 举个栗子,对于cdecl,参数是从右到左传递,堆栈平衡是由调用函数来执行的;而win32API一般使用的是stdcall,参数同样是采用了从右往左传递,而函数的堆栈平衡则是由被调用函数执行(不支持可变参数);fastcall参数直接放入寄存器而非栈中,规定前两个参数分别放入ecx和edx中,当寄存器用完时候参数才按照从右往左的顺序压入堆栈。 调用约定使用场景_cdeclc调用约定_stdcallwindows标准调用约定_fastcall快速调用约定_thiscallC++成员函数调用约定 压栈过程 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往里开辟了两个参数随后开辟新栈,进行现场保护 执行完成后回退栈针 上面的返回值是一个int类型,也就是C的内置类型,通过eax寄存器带出。 如果是一个double或者long long呢?那么可以通过eax、edx两个寄存器带出。 如果是一个自定义类型呢?其实也是类似的: 首先在参数传参过程中不能直接去push一个寄存器了,而现在是通过开辟内存后,将自定义类型的实参b的地址放入esi中,循环赋给实参。例如说自定义类型的b参数 |
CopyRight 2018-2019 实验室设备网 版权所有 |