【汇编】调用约定
概述:各种调用约定下的汇编入参方式
__fastcall
__fastcall
调用约定指定尽可能在寄存器中传递函数的自变量。 此调用约定仅适用于 x86 体系结构。 以下列表显示此调用约定的实现。
Expand table
元素 | 实现 |
---|---|
参数传递顺序 | 在自变量列表中按从左到右的顺序找到的前两个 DWORD 或更小自变量将在 ECX 和 EDX 寄存器中传递;所有其他自变量在堆栈上从右向左传递。 |
堆栈维护职责 | 已调用函数会弹出显示堆栈中的参数。 |
名称修饰约定 | At 符号 (@) 是名称的前缀;参数列表中的字节数(在十进制中)前面的 at 符号是名称的后缀。 |
大小写转换约定 | 不执行任何大小写转换。 |
类、结构和并集 | 被视为“多字节”类型(无论大小)并在堆栈上传递。 |
枚举和枚举类 | 如果它们的基础类型是通过寄存器传递的,则通过寄存器传递。 例如,如果基础类型是大小为 8、16 或 32 位的 int 或 unsigned int 。 |
Warning
区分 x64 下 [fast-call]
x64 调用约定 | Microsoft Learn
__thiscall
特定于 Microsoft**__thiscall
** 的调用约定用于 x86 体系结构上的 C++ 类成员函数。 它是成员函数使用的默认调用约定,该约定不使用变量参数(vararg
函数)。
在 __thiscall
下,被调用方清理堆栈,这对于 vararg
函数是不可能的。 自变量将从右到左推送到堆栈中。 指针 this
通过注册 ECX 传递,而不是在堆栈上传递。
在 ARM、ARM64 和 x64 计算机上,__thiscall
由编译器接受和忽略。 这是因为它们默认使用基于寄存器的调用约定。
使用 __thiscall
的原因之一是在类中成员函数默认使用 __clrcall
。 在这种情况下,可以使用 __thiscall
确保各个成员函数可以从本机代码调用。
采用 /clr:pure
进行编译时,除非另有规定,否则所有函数和函数指针都是 __clrcall
。 /clr:pure
和 /clr:safe
编译器选项在 Visual Studio 2015 中已弃用,并且在 Visual Studio 2017 中不受支持。
vararg
成员函数使用 __cdecl
调用约定。 所有函数参数都推送在堆栈上,this
指针放在最后一个堆栈上。
由于此调用约定仅适用于 C++,因此它没有 C 名称修饰方案。
在非静态类成员函数外行定义时,仅在声明中指定调用约定修饰符。 无需在行外定义上再次指定它。 编译器使用在定义点声明期间指定的调用约定。
__stdcall
编译器的命令行参数是/Gz,__stdcall是Pascal程序的缺省调用方式,大多数Windows的API也是 __stdcall 调用约定。__stdcall 函数调用约定将函数参数从右向左入栈,除非使用指针或引用类型的参数,所有参数采用传值方式传递,由被调用函数负责清除栈中的参数。对于C函数,__stdcall的名称修饰方式是在函数名字前添加下划线,在函数名字后添加@和函数参数的大小,例如:_functionname@number