我只是试图在x86汇编中进行非常快速的基于计算的编程
但我需要在调用程序之前先推累加器,计数器和数据寄存器。手动推送它们更快:
push eax
push ecx
push edx
或只是使用,
pushad
和弹出相同。谢谢
最佳答案
如果您关心性能,pusha
/ popa
几乎从不有用。它们仅在以速度为代价优化代码大小时才有用,例如保存/恢复功能周围的寄存器。但是对于非void
函数而言,这非常不方便,因为它们会重新加载所有寄存器,因此您必须将返回值存储在内存中(例如在将要加载到eax
的堆栈插槽中,或者在popad
之后要重新加载的其他位置)。
仅推送需要保存或要作为函数args传递的寄存器。或者,在inline-assembly中,只需声明任何临时注册表的"=r"(dummy1)
伪输出操作数,或在特定寄存器上使用Clobber,让编译器为您管理寄存器。正常情况下,编译器可以选择一些寄存器,它可以让您不费吹灰之力。 (或者在笨拙的MSVC样式的内联汇编中,编译器无法为您分配寄存器,因此您必须手动进行选择。编译器会分析您的汇编以查找Clobbers。)
您通常不需要保存/恢复eax
;为了提高性能,如果您不能首先计算mov esi, eax
中的值,则可能应该esi
/ call /使用esi
中的值。 ,即对需要保留call
的值使用调用保留的寄存器,因此重要值的存储/重装不在关键路径上。取而代之的是,存储/重新加载位于调用者的调用保留寄存器之一的关键路径上,您(或编译器)在整个函数中,在任何循环之外,push
/ pop
。
即使您确实想推送所有8个整数寄存器(包括esp
!),在现代CPU上使用8个单独的push
指令实际上也更快。 pusha / popa是微码的which can be a problem for the front-end。 (尽管对于uop缓存来说8个单字节指令也可能是一个问题。但是在实际代码中,通常只需要压入几个寄存器,而不是全部压入)。
如果您要针对过时的CPU(例如原始的有序Pentium和Pentium II / III)进行优化,则pusha / popa的速度将达到8 push r
或8 pop r
,实际上uops更少,因为它们没有堆栈引擎消除ESP更新指令。
从Agner Fog's instruction tables来看:现代CPU具有单字节push reg
和pop reg
,因为这些指令一直被编译器使用,因此对于性能至关重要。推/弹出吞吐量通常与存储/加载吞吐量匹配(通常每个时钟1个存储或每个时钟2个加载)。但是编译器不使用pusha
/ popa
,因此CPU设计人员没有特殊的支持来使其快速运行。如果仅运行popa
,popa
吞吐量将限制为每个时钟仅1个负载。 (我认为在Intel CPU上,最可能的性能衡量指标是popa
不使用堆栈引擎,因此它成为依赖esp
的瓶颈。)
英特尔:
pusha
:11 uops,吞吐量为8c。 popa
:18微秒/ 8c吞吐率。 pusha
:16 uops / 8c吞吐量。 popa
:18 uops / 9c吞吐量。 pusha
:18 uops / 8c吞吐量。 popa
:10微秒/ 8c吞吐率。 pusha
:10 uops / 10c吞吐量。 popa
:17 oups / 14c吞吐量。 pusha
:4/10 uops / 19c吞吐量。 popa
:4/16 uops / 14c吞吐量。 AMD:
pusha
/ popa
在某些AMD CPU(尤其是K8)上出奇地好。pusha
:9 uops,吞吐量为8c。 popa
:9微码, 4c吞吐量。 (与英特尔不同,AMD的新设计的popa
不比8x pop
差。)pusha
:9微秒/ 8c吞吐量。 popa
:9 oups / 8c吞吐量。 (Jaguar通常每个时钟只能加载一个负载。)pusha
:9微秒/ 9c吞吐量。 popa
:14微秒/ 8c吞吐率。 (Agner列出了Bulldozer系列的常规pop reg
吞吐量为每个时钟1个时钟,尽管我认为他们确实有一个堆栈引擎并且每个时钟可以进行2次加载。也许堆栈引擎一次只能处理一个堆栈指令?)pusha
:9 oups / 4c吞吐量!! (IDK怎么可能,这是表中的错误或错字,还是K8合并32位寄存器并进行四个64位存储)。 popa
:9 oups / 4c吞吐量。这些数字似乎是真实的:InstLatx86 measurements与Clawhammer(第一代K8微体系结构)上pushad
/ popad
的4c吞吐量一致。显然,AMD付出了一些努力来优化pushad
。 您标记了此inline-assembly。通常,您应该避免在inline-asm中使用
call
,因此C编译器知道该调用。关于performance - x86 Assembly pushad/popad,它有多快?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48449166/