Skip to content

调用约定


指定过程的调用方式。

调用约定决定调用代码在调用过程时如何与过程交互。它们规定了参数如何压入调用栈、值如何返回以及何时清理调用栈的规则。这些信息在与其他语言(尤其是汇编语言)编写的代码交互时非常有用。在某些情况下,调用约定还对过程名称进行某种名称修饰。

FreeBASIC 支持 3 种调用约定:stdcall、cdecl 和 pascal,分别通过 StdcallCdeclPascal 指定。调用约定可以在过程声明或定义中紧跟过程名称之后指定。过程的声明必须与定义具有相同的调用约定。

在所有调用约定中,整数过程返回值在 EAX(, EDX)寄存器中返回,浮点返回值存储在 ST(0) 寄存器中(浮点栈的顶部)。用户定义类型(UDT)值在 EAX(, EDX)寄存器中返回(如果不超过八(8)字节),否则通过将其地址压入调用栈(在任何参数之后)在内存中返回。

stdcall

在 stdcall 约定中,过程参数在过程调用之前以声明的相反顺序(即从右到左)压入调用栈(过程调用会将返回地址压入参数上方)。过程负责从调用栈中弹出任何参数(通常通过在 RET 指令后附加一个常量来指定要释放的字节数)。

stdcall 是 Windows 上的默认调用约定,以及 Extern "Windows"Extern "Windows-MS" 块内过程的默认约定。它也是 Windows API 使用的默认约定。

平台差异

  • 在 DOS 和 Windows 平台上,过程名称会添加 "@N" 后缀,其中 N 是传递的任何参数的总字节大小。

cdecl

在 cdecl 约定中,过程参数在过程调用之前以声明的相反顺序(即从右到左)压入调用栈。调用代码负责从调用栈中弹出参数。

cdecl 是 Linux、*BSD 和 DOS 上的默认调用约定,以及 Extern "C"Extern "C++" 块内过程的默认约定。它也是大多数 C 和 C++ 编译器使用的默认约定。

pascal

在 pascal 约定中,过程参数以声明的顺序(即从左到右)压入调用栈。过程负责从调用栈中弹出任何参数。

pascal 是 Pascal 和 Microsoft QuickBASIC 系列编译器使用的默认约定。

下表总结了各种调用约定之间的差异:

调用约定参数压入调用栈的方向从调用栈弹出参数的一方
stdcall从右到左过程
cdecl从右到左调用代码
pascal从左到右过程

平台差异

  • 在 DOS 和 Windows 平台上,所有调用约定都会在过程名称前添加下划线("_")前缀。
  • 默认调用约定因平台而异。Windows 上为 stdcall;而在 Linux、*BSD 和 DOS 上为 cdecl。

参见

  • Declare, Sub, Function
  • Stdcall, Cdecl, Pascal
  • Extern..End Extern

返回 目录

基于 FreeBASIC 官方文档翻译 如有侵权请联系我们删除
FreeBASIC 是开源项目,与微软公司无隶属关系