这些是什么?作为开发人员,我如何受到这些影响?
4 回答
调用约定描述了某物如何调用另一个函数。这需要将参数和状态传递给另一个函数,以便它可以正确执行和返回控制权。完成此操作的方式必须标准化和指定,以便编译器知道如何排序参数以供被调用的远程函数使用。有几种标准调用约定,但最常见的是fastcall
、stdcall
和cdecl
。
通常,术语自定义调用约定有点用词不当,指的是以下两种情况之一:
非标准调用约定或未广泛使用的调用约定(例如,如果您正在从头开始构建架构)。
编译器/链接器可以执行的一种特殊优化,它使用一次性调用约定来提高性能。
在后一种情况下,这会导致一些本来会被压入堆栈的值被存储在寄存器中。编译器将尝试根据参数在代码中的使用方式做出此决定。例如,如果该参数将用作循环索引的最大值,以便将索引与每次迭代的最大值进行比较,以查看是否应该继续,这将是一个将其移至登记。
如果执行优化,这通常会减少代码大小并提高性能。
作为开发人员,我如何受到这些影响?
从您作为开发人员的角度来看,您可能不在乎;这是一个会自动发生的优化。
每种语言在调用函数时都有一个约定,哪些参数将在寄存器变量和堆栈中传递,以及如何返回返回值。
有时会使用与标准不同的约定,这称为自定义调用约定。
这在不同语言之间进行互操作时最常见。例如,C 和 Pascal 关于如何传递参数有不同的约定。从 C 的角度来看,Pascal 调用约定可以称为自定义调用约定。
我不认为你真的需要关心。
正常的调用约定类似于 __stdcall 和 __fastcall。它们确定您的调用签名如何转换为堆栈布局,谁(调用者或被调用者)负责保存和恢复寄存器等。例如,__fastcall 应该使用更多的寄存器,而 __stdcall 会使用更多的堆栈。
自定义调用约定专门针对特定函数及其使用方式进行了优化。IIRC,它们只发生在特定模块的本地函数中。这就是编译器如何了解它的使用方式以及您如何知道没有外部调用者需要能够指定约定的方式。
基于此,您的编译器将在适当的情况下自动使用它们,您的代码将运行得更快和/或占用更少的空间,但您并不需要担心。
除非您直接操作堆栈或编写引用局部变量的内联汇编,否则它不会影响您。或者,如果您与通过不同调用约定链接的库进行交互
它是什么:大多数编译器等使用标准调用约定,例如 cdecl,其中函数参数按特定顺序推送到堆栈等。