【汇编】调用约定

概述:各种调用约定下的汇编入参方式

参考文章:自变量传递和命名约定 | Microsoft Learn

__fastcall

__fastcall | Microsoft Learn

__fastcall 调用约定指定尽可能在寄存器中传递函数的自变量。 此调用约定仅适用于 x86 体系结构。 以下列表显示此调用约定的实现。

Expand table

元素 实现
参数传递顺序 在自变量列表中按从左到右的顺序找到的前两个 DWORD 或更小自变量将在 ECX 和 EDX 寄存器中传递;所有其他自变量在堆栈上从右向左传递。
堆栈维护职责 已调用函数会弹出显示堆栈中的参数。
名称修饰约定 At 符号 (@) 是名称的前缀;参数列表中的字节数(在十进制中)前面的 at 符号是名称的后缀。
大小写转换约定 不执行任何大小写转换。
类、结构和并集 被视为“多字节”类型(无论大小)并在堆栈上传递。
枚举和枚举类 如果它们的基础类型是通过寄存器传递的,则通过寄存器传递。 例如,如果基础类型是大小为 8、16 或 32 位的 intunsigned 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


【汇编】调用约定
https://hodlyounger.github.io/B_Code/汇编/【汇编】调用约定/
作者
mingming
发布于
2023年12月6日
许可协议