Assembly 为什么有些Windows booloader用'sub'而不是'xor'编码零寄存器?

Assembly 为什么有些Windows booloader用'sub'而不是'xor'编码零寄存器?,assembly,x86,micro-optimization,zero-initialization,Assembly,X86,Micro Optimization,Zero Initialization,考虑到如中所述的考虑因素,似乎将寄存器归零的最佳方法是xor reg,reg。但当我检查真实世界的汇编代码(如Windows引导加载程序代码,IIRC)时,我看到使用了xor reg,reg和sub reg,reg 为什么要将sub用于此目的?在某些特殊情况下,是否有任何理由选择sub?例如,它设置的标志是否与xor不同?在许多现代x86处理器上,xor-reg,reg和sub-reg,reg都被视为调零习惯用法。两者的效果相同,使用其中一种对另一种没有好处。差异: 记录设置AF=0(BCD半

考虑到如中所述的考虑因素,似乎将寄存器归零的最佳方法是
xor reg,reg
。但当我检查真实世界的汇编代码(如Windows引导加载程序代码,IIRC)时,我看到使用了
xor reg,reg
sub reg,reg


为什么要将
sub
用于此目的?在某些特殊情况下,是否有任何理由选择
sub
?例如,它设置的标志是否与
xor
不同?

在许多现代x86处理器上,
xor-reg,reg
sub-reg,reg
都被视为调零习惯用法。两者的效果相同,使用其中一种对另一种没有好处。

差异:

  • 记录设置AF=0(BCD半进位标志,从第3位到第4位)。叶AF未定义。建筑效果在其他方面完全相同,只留下可能的性能差异。AF几乎不重要,通常只有在下一条指令是
    aaa
    或其他指令时才重要
  • sub
    -在少数CPU(如中所指出的Silvermont)上,归零比xor归零慢,但在大多数CPU上的性能相同。当然,两者都有相同的2字节大小
我猜这只是手工编写的asm的不同作者,他们中的一些人更喜欢
sub
,可能没有意识到有些CPU只是特例xor。除非他们希望保证清除AF标志,否则可能是有意的
sub
。比如,在可能使用
pushf
的东西之前,可能初始化东西并希望EFLAGS有一个完全已知的状态

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


在将
sub
识别为归零习惯用法的现代CPU中,它将为零,因此CPU可以完全相同地处理异或归零和次归零,包括标记结果。

那么为什么不总是一个或另一个呢?为什么在同一代码中混合使用这两种代码?建议某些机器优化
xor
优于
sub
。另一方面,引导加载器代码对性能并不重要,因此可能没有人关心。与异或不同,减法运算是在小学教授的,因此使用异或清除寄存器对初学者来说可能更神秘。当我想用数字零填充寄存器时,我更喜欢SUB,当我想用布尔零填充寄存器时,我更喜欢XOR。程序员首选项。看看那是什么a86?指令集还为某些指令提供了不止一种从asm编码机器代码的方法,因此该汇编程序声称它将在机器代码中留下一个足迹,以便能够确定您是否使用了该汇编程序。如果他们选择将您的xor转换为sub,或者如果他们检测到它们,则可以在程序集级别使用它。我认为
sub-reg,reg
将清除AF标志,而
xor-reg,reg
将不定义它。如果现实生活中有人需要这种效果,我会感到震惊。除此之外,它们都应该设置ZF、PF和clear SF、OF、CF。变化可能只是程序员不知道或不关心微小的性能差异。也可能是一个标志,按位运算往往不会像减法运算那样处理太多的标志,减法运算应该处理所有的标志(一般来说,不是特定于任何一个指令集)因此此sub不仅会将某些内容归零,而且会将标志置于已知状态。此sub可能纯粹用于标志,而不是寄存器。哈,你先按enter键…”为什么像这样的问题需要直接问代码的作者,因为我们无法读懂他们的想法,尤其是在做出决定和编写代码之后。指令对齐或类似的东西有什么区别吗?@MichaelK没有。两条指令都有相同的编码,但有不同的操作码。没有意识到有些CP仅限美国的特殊情况xor。-或者可能是在Silvermont出现之前编写的,当时可能没有任何CPU的次调零速度可能较慢。