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

时间:2017-05-01 23:05:05

标签: linux assembly x86 mips

在MIPS中,参数放在$ a0到$ a4寄存器中,以便更快地访问。为什么有些x86架构会将设计选择放在堆栈而不是寄存器中?这样做有什么好处?

3 个答案:

答案 0 :(得分:4)

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

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

即使在Microsoft Visual C ++编译器生成的C / C ++代码中,尽管最常见的调用约定__cdecl和__stdcall使用堆栈,但第三个__fastcall使用寄存器。而且,我看到使用两者的汇编代码;如果它需要与C通信,寄存器中的例程预期参数,但只接收来自库中其他例程的调用的私有例程使用寄存器。

答案 1 :(得分:2)

寄存器自然更快,速度更快,但您必须拥有足够的寄存器。 x86传统上只有非常少的寄存器,所以基于堆栈的方法是要走的路,在历史上它通常是走的路,risc和其他人带来了更多的寄存器和第一个使用寄存器的想法现在需要考虑的几个参数和可能的返回值。 x86现在有更多的寄存器,但一般都是基于堆栈的,虽然我认为zortech或watcom或者甚至gcc现在有一个命令行选项来使用一些寄存器,必须通过研究确认或否认。但历史上它已经将堆栈用于参数和寄存器。

ARM,MIPS等都有有限数量的寄存器,因此最终会转储到堆栈中,如果您保留/控制参数数量和大小,有时可以尝试限制并提高性能。

在一天结束时,底线是某人或某个团队定义调用约定,它最终是编译器作者的选择,如果芯片/处理器设计者有建议,编译器定义其调用约定无关紧要是遵循建议还是做自己的事情。没有理由创建一个主要基于堆栈的MIPS或ARM编译器/工具链(指令集本身可能会指示基于堆栈或寄存器的返回,或者它可能是可选的),同样欢迎使用x86编译器。一个以寄存器开头的约定然后在使用了一些数量后移动到堆栈。

所以有点历史和一点点因为他们选择......

答案 2 :(得分:1)

简单的答案是,您必须始终遵循正在运行的平台的ABI。更长的答案是您错误地假设每个32位x86平台将专门使用堆栈进行参数传递。事实上,虽然每个平台都采用标准,但有许多方法,其中任何一种都可以使用。 (fastcall,cdecl等)