为什么 x86 将参数放在堆栈上?

Tin*_*yik 0 linux x86 assembly mips

在 MIPS 中,参数被放置在 $a0 到 $a4 寄存器中以实现更快的访问。为什么某些 x86 架构选择将参数放置在堆栈上而不是寄存器中?这样做有什么好处呢?

Dav*_*ray 5

真正的答案是,它更多地取决于编译器而不是处理器,尽管我怀疑 x86 编译器将参数推入堆栈如此常见的原因是 x86 CPU 一直遭受寄存器稀缺的困扰。当你消除保留寄存器时,剩下三个——EAX、ECX和EDX,它们对应于原始16位x86指令集中的AX、CX和DX。据我所知,Intel 系列中第一个提高该限制的处理器是 64 位“AMD”架构,它又增加了 8 个处理器,编号为 R9 到 R15。五个保留寄存器获得新名称,但它们仍然保留。

为了强化我的观点,即它取决于编译器,您只需看看 Microsoft .NET Framework 附带的本机代码生成器,它展示了一种混合方法,其中前两个参数进入 ECX(或 RCX)和 EDX (或 RDX),而其他参数则进入堆栈。

即使在 Microsoft Visual C++ 编译器生成的 C/C++ 代码中,尽管最常见的调用约定 __cdecl 和 __stdcall 使用堆栈,但第三种调用约定 __fastcall 使用寄存器。此外,我见过使用两者的汇编代码;如果需要与 C 对话,则例程需要寄存器中的参数,但仅接收来自库中其他例程的调用的私有例程使用寄存器。

  • Microsoft [fastcall 约定](https://msdn.microsoft.com/en-us/library/6xa169sk.aspx) 使用 ECX 和 EDX 作为前两个参数。[64 位调用约定](https://msdn.microsoft.com/en-us/library/ms235286.aspx) 使用 ECX、EDX、R8 和 R9 作为前四个参数(和/或前四个 xmm浮点寄存器)。 (2认同)