🗒️函数调用约定
技术分享|2024-10-8|最后更新: 2024-12-16
type
status
date
slug
summary
tags
category
icon
password

BG

高级语言的函数编译成机器码的时候,存在一个潜在问题:CPU没办法知道一个函数调用需要多少个、什么样的参数。为此,计算机提供了栈来支持参数的传递。这样,在函数调用的时候,先将参数压栈,然后CALL,函数里在从堆栈获取数据。
而在参数传递的时候,有两个问题需要明确说明:
  • 当参数个数大于1的时候,按照什么顺序压入堆栈
  • 函数调用后,由谁恢复堆栈
  • 函数的返回值放在哪
因此,引入函数调用规范。

Calling Conventions

  • stdcall
  • cdecl
  • fastcall
  • thiscall
  • nakedcall

stdcall

  • 参数从右向左压入堆栈
  • 函数自身修改堆栈
  • 函数的装饰名(decoration name/mangling name)为函数名自动加前导的下划线, 后面紧跟一个@符号, 其后紧跟着参数的尺寸

cdecl

cdecl调用约定又称为C调用约定, 是C语言缺省的调用约定, 它的定义语法是:
cdecl调用约定的特点如下:
  • 参数从右向左压入堆栈
  • 由调用者恢复堆栈,这使得cdecl调用约定可以支持变参函数
  • 函数的装饰名以下划线开头,后面紧跟着函数名

fastcall

fastcall调用约定是为了提高函数调用效率而设计的,它的定义语法是:
fastcall调用约定的特点如下:
  • 前两个DWORD类型或者更小的参数放入寄存器ECX和EDX中,其他参数从右向左压入堆栈
  • 函数自身修改堆栈
  • 函数的装饰名以@开头,后面紧跟着函数名,然后是@和参数的尺寸

thiscall

thiscall调用约定是C++成员函数缺省的调用约定,它的定义语法是:
thiscall调用约定的特点如下:
  • ECX寄存器存放着this指针
  • 参数从右向左压入堆栈
  • 函数自身清理堆栈

nakedcall

nakedcall调用约定是一种特殊的调用约定,它允许程序员完全控制函数的序言和结尾代码。它的定义语法是:
nakedcall调用约定的特点如下:
  • 编译器不会生成任何函数的序言和结尾代码
  • 程序员必须自己编写所有的汇编代码,包括参数的获取和堆栈的维护
  • 通常用于编写底层的系统代码或驱动程序

总结

  • 函数调用约定定义了参数传递顺序、堆栈恢复方式和返回值位置等规则
  • stdcall:参数从右向左入栈,函数自身清理堆栈
  • cdecl:参数从右向左入栈,调用者清理堆栈,支持变参
  • fastcall:首两个参数使用寄存器传递,提高效率
  • thiscall:C++成员函数默认约定,ECX存放this指针
  • nakedcall:完全由程序员控制函数代码生成,用于底层编程
周期分离的三角函数Real-Time Grass Rendering for General 3D Scenes
Loading...