x86/x64 程序集的旋转或移位

Rotation or Shifting with x86/x64 Assembly

我有一个正在用汇编编写的函数,我想确定什么能给我最好的吞吐量。

我在 RAX 中有一个 64 位值,我需要获取最高字节并对其执行一些操作,我想知道解决这个问题的最佳方法是什么。

shr  rax, 56    ; This will get me the most significant byte in al.

然而,这比...更有效吗

rol  rax, 8
and  rax, r12   ; I already have the value 255 in r12

我之所以要问,是因为在某些架构上,换档速度是您换档次数的函数。如果我记得,在 680x0 芯片上它是 6 + 2n,其中 n 是移位计数。我不认为这在 x86 体系结构上是正确的,但我不确定......所以希望人们提供一些启发。 (我了解延迟)

或者是否有一种简单的方法可以将 RAX 的位 0-31 与位 32-64 交换而不是旋转或移位?类似于交换在 680x0 上所做的事情。

根据 http://agner.org/optimize/ 处的指令表,立即计数的 rol 是一个 single-uop/m-op 指令,在 Intel(Pentium M 到 Haswell)和 AMD(K8压路机)。吞吐量范围从每个时钟 1 个到每个时钟 3 个。

使用可变计数 (rol r, cl) 旋转在 Intel 上较慢,在 AMD 上速度相同。

显然,如果您要问这类问题,请阅读 Agner Fog 的指南,因为高性能比单独使用单个指令更重要。


如果您在多个数据项上执行此操作,您可以同时在 16B(xmm 向 SSE 注册)或 32B(ymm 向 AVX 注册)块上使用矢量洗牌。 pshufd xmm, xmm, imm 将允许您为每个输出双字选择任何输入双字。 (这样你就可以广播和其他东西,也可以只是随机播放。)