-
-
[原创]深入理解C语言二-函数调用约定
-
发表于: 2021-7-5 23:26 5024
-
调用者和被调用者关于栈上参数传递和清理栈空间的一种约定,用来清理参数占用的栈空间,恢复栈平衡。栈平衡是编译器在汇编时完成的,不需要手动完成。
系统中的寄存器,存储CPU要读取的指令地址,CPU通过eip寄存器读取即将要执行的指令,每次CPU执行完相应的汇编指令后,eip的值就会增加。栈中的返回地址存放在eip中,供当前函数执行完后,CPU执行程序的下一条语句。
栈指针寄存器,一直指向系统栈最上面一个栈帧的栈顶,是CPU机制决定的,push、pop指令会自动调整esp的值。
基址指针寄存器,一直指向系统栈最上面一个栈帧的栈底,ebp只存取某时刻的esp,这个时刻是指进入一个函数内部后,CPU会将esp的值赋值给ebp,此时就可以通过ebp对栈进行操作,比如获取函数参数、局部变量等。
esp在函数运行时会不断变化,所以保存一个进入某个函数的esp到ebp,方便访问参数和局部变量,还方便调试器分析函数调用过程中的堆栈情况。
- 参数入栈顺序:从右向左
- 调用者修改栈,恢复栈平衡,所以可以支持变参函数
- 参数入栈顺序:从右向左
- 被调用者自身修改栈,恢复栈平衡
- 参数入栈顺序:函数的第一、第二个参数通过ecx、edx寄存器传递,剩余参数从右向左入栈
- 被调用者自身修改栈,恢复栈平衡
- x64传递参数时比x86多了两个寄存器r8、r9
- x64参数入栈对齐到8个字节,x86是4个字节
- x64函数的前4个参数通过rcx、rdx、r8、r9四个寄存器传递
- x64会在栈上预留4个字节的内存空间
- x64调用者恢复栈平衡,支持变参函数
- x64栈整体大小要能被16整除
- x64局部变量空间的分配和初始化由调用者完成
- cdecl(C语言默认,变参函数)
- stdcall(Windows API,内核驱动)
- fastcall(x64平台)
赞赏
他的文章
- [分享]C++基础十七-异常机制 8580
- [分享]C++基础十六-模板 8941
- [分享]C++基础十五-运算符重载 8964
- [分享]C++基础十四-抽象类 8677
- [分享]C++基础十三-多态 8477
看原图
赞赏
雪币:
留言: