Ibr*_*pek 1 assembly x86-64 function-parameter
在x86-32汇编中,参数存储在堆栈中,但在x86-64中,参数存储在寄存器中.这是什么原因?
存储/重新加载往返接收指令并花费大约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向量的规则,而不是在堆栈上).
有关存储转发延迟的更多详细信息,请参阅x86标记wiki以获取调用约定文档的链接和性能链接.