条件指令(cmov)和跳转指令之间的区别

时间:2014-10-02 04:28:30

标签: performance assembly instructions mov

我很困惑在哪里使用cmov说明以及在汇编中使用jump指令的位置?

效果的角度来看:

  • 两者有什么不同?
  • 哪一个更好?

如果可能,请通过示例解释他们的不同之处。

1 个答案:

答案 0 :(得分:16)

movcc 是所谓的谓词指令。这就是说,这个指令在条件(谓词)"下执行。

在执行算术运算(尤其是比较指令)之后,许多处理器(包括x86)设置条件代码位以指示操作结果的状态。

条件跳转指令检查条件代码位的状态,如果为真,则跳转到指定的目标。

因为跳转是有条件的,并且处理器通常具有深度流水线,所以当CPU遇到jmp指令时,条件代码位实际上还没有准备好让jmp指令处理。芯片设计人员可以简单地等待管道耗尽(通常是很多时钟周期),然后执行jmp,但这会使处理器变慢。

相反,他们中的大多数人选择使用分支预测算法,该算法预测条件跳转的方式。处理器然后可以获取,解码和执行预测的分支(或不执行),并继续快速执行,条件是如果最终到达的条件代码位变为错误对于条件( branch mispredict ),处理器撤消分支后它所做的所有工作,并重新执行沿另一条路径运行的程序。

条件跳转对于流水线执行比正常数据依赖更难,因为它们可以更改流经管道的指令流中的下一条指令。这称为control dependency,而不是数据依赖(如add,其中两个输入都是其他最近指令的输出)。

分支预测变得非常好,因为大多数分支往往偏向于他们的方向。 (大多数循环结束时的分支,通常会分支回到顶部)。所以大部分时间处理器都不必退出错误预测的工作。

如果分支的方向高度不可预测,则处理器将在大约50%的时间内猜错,因此必须退出工作。这很贵。

好的,现在,人们常常找到这样的代码:

  cmp   ...
  jcc   $
  mov   register1, register2
$: ; continue here
  ...
  ; use register1

如果分支预测器猜对了,那么无论分支走哪条,这段代码都很快。如果猜错了很多......哎哟。

因此条件移动指令。这是根据条件代码位有条件地移动数据的移动。我们可以改写上面的内容:

  cmp   ...
  movcc  register1, register2
$: ; continue here
  ...
  ; use register1

现在我们没有分支指令,因此没有错误预测使处理器撤消所有工作。由于没有控制依赖性,因此无论movccmov还是nop,都需要提取和解码以下指令。管道可以保持完整而不预测条件并推测性地执行使用register1的指令。 (你可以用这种方式构建一个CPU,但它会破坏movcc的目的。)

movcc将控件依赖项转换为数据依赖项。 CPU将其视为一个3输入数学指令,其输入为EFLAGS,其输入为两个"常规"输入(dest寄存器和源寄存器或存储器)。在x86上,adccmovae(mov if CF==0)完全相同,无序执行跟踪依赖关系:输入是CF,还有两个GP寄存器。输出是目标寄存器。

对于x86,每个条件组合cc都有cmovccjccsetcc条指令。 (setcc根据条件将目标设置为0或1。因此它对标志有数据依赖性,没有其他输入依赖性。)