首页
社区
课程
招聘
[原创]深入理解C语言二-函数调用约定
2021-7-5 23:26 4288

[原创]深入理解C语言二-函数调用约定

2021-7-5 23:26
4288

函数调用约定

调用者和被调用者关于栈上参数传递和清理栈空间的一种约定,用来清理参数占用的栈空间,恢复栈平衡。栈平衡是编译器在汇编时完成的,不需要手动完成。

调用约定的类型

  1. cdecl(C语言默认,变参函数)
  2. stdcall(Windows API,内核驱动)
  3. fastcall(x64平台)

cdecl调用约定

  • 参数入栈顺序:从右向左
  • 调用者修改栈,恢复栈平衡,所以可以支持变参函数

stdcall调用约定

  • 参数入栈顺序:从右向左
  • 被调用者自身修改栈,恢复栈平衡

fastcall调用约定

  • 参数入栈顺序:函数的第一、第二个参数通过ecx、edx寄存器传递,剩余参数从右向左入栈
  • 被调用者自身修改栈,恢复栈平衡

EIP

系统中的寄存器,存储CPU要读取的指令地址,CPU通过eip寄存器读取即将要执行的指令,每次CPU执行完相应的汇编指令后,eip的值就会增加。栈中的返回地址存放在eip中,供当前函数执行完后,CPU执行程序的下一条语句。

ESP

栈指针寄存器,一直指向系统栈最上面一个栈帧的栈顶,是CPU机制决定的,push、pop指令会自动调整esp的值。

EBP

基址指针寄存器,一直指向系统栈最上面一个栈帧的栈底,ebp只存取某时刻的esp,这个时刻是指进入一个函数内部后,CPU会将esp的值赋值给ebp,此时就可以通过ebp对栈进行操作,比如获取函数参数、局部变量等。
esp在函数运行时会不断变化,所以保存一个进入某个函数的esp到ebp,方便访问参数和局部变量,还方便调试器分析函数调用过程中的堆栈情况。

x86和x64的fastcall的区别

  • x64传递参数时比x86多了两个寄存器r8、r9
  • x64参数入栈对齐到8个字节,x86是4个字节
  • x64函数的前4个参数通过rcx、rdx、r8、r9四个寄存器传递
  • x64会在栈上预留4个字节的内存空间
  • x64调用者恢复栈平衡,支持变参函数
  • x64栈整体大小要能被16整除
  • x64局部变量空间的分配和初始化由调用者完成

github:https://github.com/0I00II000I00I0I0

bilibili:https://space.bilibili.com/284022506


[培训]内核驱动高级班,冲击BAT一流互联网大厂工 作,每周日13:00-18:00直播授课

收藏
点赞1
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回