为什么某些 Windows booloader 代码使用 `sub` 而不是 `xor` 将寄存器归零?

Mic*_*elK 2 x86 assembly micro-optimization zero-initialization

考虑到如/sf/answers/2356780681/ 中详述的考虑,这似乎xor reg, reg是将寄存器清零的最佳方法。但是当我审视现实世界的汇编代码(如Windows Bootloader代码,IIRC),我看到这两个xor reg, regsub reg, reg使用了。

为什么sub完全用于此目的?sub在某些特殊情况下有什么理由更喜欢吗?例如,它设置的标志是否与xor?

Pet*_*des 8

区别:

  • sub reg,reg记录设置为 AF=0(BCD 半进位标志,从第 3 位到第 4 位)。 XOR使 AF 未定义。架构效果在其他方面完全相同,仅留下可能的性能差异。AF 几乎从不重要,通常只有在下一条指令是aaa什么时才重要。
  • sub-zeroing 在一些 CPU 上比 xor-zeroing 慢(例如 Silvermont,正如你链接的回答中指出的那样),但在大多数CPU 上的性能相同。当然,两者都具有相同的 2 字节大小。

我猜这只是手写 asm 的不同作者,他们中的一些人sub可能更喜欢而没有意识到有些 CPU 只是特殊情况的异或。除非他们想保证清除 AF 标志,否则sub可能是故意的。就像可能初始化事物并希望在可能使用的事物之前为 EFLAGS 提供一个完全已知的状态pushf.

XOR 未定义 AF 仍然意味着它将是 0 或 1,您只是不知道哪个。(不像 C 未定义的行为)。实际结果可能取决于 CPU 型号、输入值,甚至可能是某处的一些杂散位。

在识别sub为归零习语的现代 CPU 中,它将为零,因此 CPU 可以完全相同地处理异或归零和子归零,包括 FLAGS 结果。