【发布时间】:2010-08-06 22:49:01
【问题描述】:
从历史上看,为什么似乎每个人和他们的小弟都定义了自己的调用约定?你有 C、C++、Windows、Pascal、Fortran、Fastcall 以及可能还有无数其他我没想到会提到的东西。对于绝大多数用例来说,一种约定不应该是最有效的吗?有什么好的理由偏爱其中一个吗?
【问题讨论】:
标签: assembly history low-level calling-convention
从历史上看,为什么似乎每个人和他们的小弟都定义了自己的调用约定?你有 C、C++、Windows、Pascal、Fortran、Fastcall 以及可能还有无数其他我没想到会提到的东西。对于绝大多数用例来说,一种约定不应该是最有效的吗?有什么好的理由偏爱其中一个吗?
【问题讨论】:
标签: assembly history low-level calling-convention
您提到的调用约定是数十年来针对不同语言和不同硬件设计的。他们都有不同的目标。 cdecl 支持 printf 的可变参数。 stdcall 导致更小的代码生成,但没有可变参数。 Fastcall 可以极大地加速在旧机器上仅使用一两个参数的简单函数的性能(但现在很少加速。)
请注意,在引入 x64 时,至少在 Windows 上,它被设计为具有单一的调用约定。
Raymond Chen写了一个关于调用约定历史的精彩系列,可以开始here。
【讨论】:
因为从历史上看,每个人和他们的小弟确实定义了自己的调用约定。它们都是为不同的目的而创建的,因此由不同的性能需求驱动。例如,C++ 倾向于对传递 this 参数进行优化。
【讨论】:
【讨论】:
部分原因是微处理器(或处理器)的底层架构。大多数语言从特定的 CPU 开始,并与该架构有点纠缠不清。例如,旧的 Univac 1100 系列计算机甚至没有调用堆栈!
另一部分原因是,除非您尝试了几种做事方式,否则无法预见最佳解决方案。
【讨论】:
它们是为不同的目的而创建的,并具有不同的优化系统。
例如,为了减少“堆栈溢出”(不是双关语),有些人想到了各种想法来调用函数以使堆栈溢出不可能。
另一个例子是 Lambda 演算。不要太模糊,但在 Lambda 中,函数可能只传递一个参数并返回一个值,因此也需要自己的调用约定。
【讨论】: