【问题标题】:why use or instead of cmp when checking against 0 [duplicate]为什么在检查 0 时使用 or 而不是 cmp [重复]
【发布时间】:2017-08-12 03:13:16
【问题描述】:

当使用“or”而不是“cmp”时,是否有重要的积极意义?

考虑这个函数序言:

push  ebp
mov   ebp,esp
push  ebx

xor   eax,eax        ;error return code
mov   ecx,[ebp +8]   ;first integer arg after return addr.
mov   edx,[ebp +12]  ;second integer argument

该函数应计算a / ba % b
首先我需要检查一个 0 除数。

我的直觉是组装

cmp  edx,0
je   InvalidDivisor

但是当我查看有关汇编程序的高级书籍时,会使用这个:

or   edx,edx
jz   InvalidDivisor   

我的问题是为什么第二种解决方案“更正确”?
计算或运算并检查零标志是否比仅比较两个值需要更长的时间?

这只是更高级的编码风格的问题吗?

【问题讨论】:

  • 它们具有相同的延迟和吞吐量,但or 形式更小,因为不需要将立即数编码到机器代码中。
  • 这个已经问了好几次了,需要找到重复的链接...

标签: assembly x86


【解决方案1】:

虽然问题中的示例适用于 Intel x86,但 CMP 和 OR 指令也存在于其他处理器中。

在 MOS 6502 上,没有那么多寄存器,您也可能在状态标志中传递参数或返回值,您可能希望避免影响 C 标志的指令。因此,与 CMP 相比,您可能更喜欢 EOR(异或)、AND 或 OR。在 6502 上,几乎所有复制数据的指令都会影响 N 和 Z 标志。

在 Atmel 8 位 AVR 微控制器系列上,如果我没记错的话,有一条方便的指令 CPSE(如果相等则比较并跳过)它不会影响任何标志。 AVR-GCC 将 32 个寄存器中的一个指定为“零寄存器”,然后发出代码以将 CPSE 与该寄存器一起使用。

【讨论】:

    【解决方案2】:

    or edx,edx 是两个字节,cmp edx, 0 是三个字节,所以如果您关心大小,您知道该选择哪个。

    如果您更关心速度,那么您实际上需要测量。 Or 显然会“改变”寄存器,如果下一条指令使用相同的寄存器,可能会增加延迟。

    The best choice for comparing a register with zero is test reg, reg.

    83 fa 00  cmp    edx,0x0
    09 d2     or     edx,edx ; Smaller
    85 d2     test   edx,edx ; Smaller and better, updates ZF but does not store the result
    

    【讨论】:

    • 选择这个答案是因为安德斯发布了一个更复杂的解释的链接,为所有其他海报欢呼,非常感谢
    【解决方案3】:

    两条指令汇编为:

    83 fa 00                cmp    edx,0x0
    09 d2                   or     edx,edx
    

    正如您所见,使用or 更短(因此在运行时加载的代码更少)并且具有相同的效果。但是实际上使用起来更好:

    85 d2                   test   edx,edx 
    

    如果edx 为零并且进一步的操作知道它们不需要依赖结果,即使 CPU 还没有弄清楚,它也会设置零标志。

    【讨论】:

      【解决方案4】:

      您没有明确说明这是用于什么处理器,但笼统地说:

      您使用汇编程序进行编码,因此您关心内存和时钟周期。

      您要做的就是检测 EAX 是否为零。 如果 EAX 为零,ORinx EAX 本身将设置 Z 状态位,对 EAX 的内容没有任何副作用,并且比直接与零比较更快。

      将寄存器与立即值进行比较可能需要(至少)一个额外的周期来加载,并且对于常量值“0”需要一个额外的字节(或 2 或 4)。
      另一方面,寄存器数量有限,对 EAX 的引用很可能直接在指令中使用 3 或 4 位进行编码。

      【讨论】:

      • 实际的 x86 CPU 可以在同一时钟周期内解码 3 字节的 cmp 以及多达 3 或 4 条其他指令。但是,是的,代码大小是 cmp reg,imm8or reg,reg 的劣势。在很多情况下,3 字节的 cmp 比 2 字节的 or 更好,但是,在乱序的 exec CPU 上,所以这不是全部。幸运的是 test reg,reg 让我们两全其美。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-07
      • 2011-05-19
      • 2021-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-22
      相关资源
      最近更新 更多