为什么参数存储在寄存器中而不是存储在x86-64汇编中的堆栈中?

Ibr*_*pek 1 assembly x86-64 function-parameter

在x86-32汇编中,参数存储在堆栈中,但在x86-64中,参数存储在寄存器中.这是什么原因?

Thi*_*ilo 9

访问CPU寄存器(访问RAM)要快得多(很多).

由于64位CPU具有更多通用寄存器(与64位无关,只是因为它们更新/更大),因此使用它们是有意义的.


Pet*_*des 5

存储/重新加载往返接收指令并花费大约6个周期的存储转发延迟,因此现代调用约定使用更高效的设计.在某些情况下,这也会保存指令,因为调用者只能在寄存器中生成arg而不是推送它.(并且不必在返回后弹出堆栈).

由于x86-64是一种新模式,它对后向兼容没有任何要求,因此可以设计一个没有传统行李的全新ABI.有关x86-64 SysV调用约定的设计历史以及为什么它比Windows x86-64调用约定更有效,请参阅此答案.(红色区域,更多arg传递寄存器.)它比Windows惯例更复杂,特别是对于varargs函数.


在寄存器中传递第一对args在32位代码中也更有效,但是引入新的调用约定会打破向后兼容库.

即便如此,MS也用__fastcall/ __vectorcall来做,即使在32位模式下也使用两个调用寄存器寄存器(ecx和edx)进行arg传递.这些调用约定的64位版本使用更多arg传递寄存器,因为x86-64具有更多GP寄存器.

Unix/Linux并没有尝试引入一个32位的新调用约定,基本上只是放弃32位作为过时的遗留代码,这些代码一直很慢.(尽管32位SysV ABI扩展了在向量regs中传递/返回16B SSE和32B AVX向量的规则,而不是在堆栈上).

有关存储转发延迟的更多详细信息,请参阅标记wiki以获取调用约定文档的链接和性能链接.