1

首先,我想说我是 ASM 新手,如果这是一个愚蠢的问题,请原谅。

我在Agner Fog 的微架构手册中阅读了有关部分寄存器停顿的信息(这似乎有点高级,但我很好奇为什么 64 位模式下的 32 位指令将寄存器的上半部分归零)。例 6.13 给出了如何避免寄存器停顿的解决方案。我对此仍然有些困惑,为什么不使用 OR 操作而不是 MOV,如下所示:

xor eax, eax
mov al, byte [mem8]
; or  al, byte [mem8] ; why not this?

我觉得效果是一样的。它们每秒都使用相同数量的周期吗?一个比另一个更有效吗?有没有什么“幕后”让我更喜欢其中一个?

4

1 回答 1

2

64 位模式下的部分寄存器访问

在 64 位模式下,访问小于 64 位的寄存器时适用以下规则:

  • 如果访问 32 位寄存器,则相关 64 位寄存器的高 32 位被清除
  • 如果访问 16 位或 8 位寄存器,则相关 64 位寄存器的高 48 位或 56 位保留。

如果只访问一个 8 位寄存器,则必须先获取相关 64 位寄存器的旧值,更改 8 位子寄存器,然后保存新值。

Agner Fog 的微体系结构手册中的示例 6.13与此无关,它只是 的替代方法movzx,因为此指令在较旧的奔腾处理器上很慢。

mov还是or

两条线

31 C0                   xor eax, eax
8A 05 ## ## ## ##       mov al, byte [mem8]

(左侧的操作码)可能比将第二行替换为更快

0A 05 ## ## ## ##       or  al, byte [mem8]

因为对上一行存在依赖关系:只有在xor eax, eax计算出新值时 eax才能将 in 传递给or. 此外,与 with 的变体一样mov,可能会因为只访问部分寄存器而减慢速度。相反,我建议将这两行替换为

0F B6 05 ## ## ## ##    movzx eax, byte [mem8]

这比前一种方法短一个字节,而且也只是一条访问完整 32 位寄存器的指令。正如阿格纳雾所说

避免部分寄存器停顿的最简单方法是始终使用完整寄存器并在从较小的内存操作数读取时使用MOVZX或。MOVSX

于 2020-07-16T20:03:35.703 回答