条件指令(cmov)和跳转指令之间的区别 [英] difference between conditional instructions (cmov) and jump instructions

查看:848
本文介绍了条件指令(cmov)和跳转指令之间的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很困惑在汇编中在哪里使用cmov指令以及在哪里使用jump指令?

I'm confused where to use cmov instructions and where to use jump instructions in assembly?

性能的角度来看:

  • 两者的区别是什么?
  • 哪个更好?

如果可能,请举例说明它们的区别.

If possible, please explain their difference with an example.

推荐答案

movcc 是所谓的 predicated 指令.花哨的是该指令在条件(谓词)下执行"的意思.

movcc is a so-called predicated instruction. That's fancy-speak for "this instruction executes under a condition (predicate)".

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

Many processors, including the x86, after doing an arithmetic operation (especially compare instructions), sets the condition code bits to indicate the status of the result of the operation.

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

A conditional jump instruction checks the condition code bits for a status, and if true, jumps to a designated target.

由于跳转是有条件的,并且处理器通常具有较深的流水线,因此当CPU遇到jmp指令时,条件码位可能实际上未准备好让jmp指令处理.芯片设计人员可以简单地等待流水线耗尽(通常需要很多时钟周期),然后执行jmp,但这会使处理器变慢.

Because the jump is conditional, and the processor typically has a deep pipeline, the condition code bits may literally not ready for the jmp instruction to process when the CPU encounters the jmp instruction. The chip designers could simply wait for the pipeline to drain (often many clock cycles), and then execute the jmp, but that would make the processor slow.

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

Instead, most of them choose to have a branch prediction algorithm, which predicts which way a conditional jump will go. The processor can then fetch, decode, and execute the predicted branch (or not), and continue fast execution, with the proviso that if the condition code bits that finally arrive turn out to be wrong for conditional (branch mispredict), the processor undoes all work it did after the branch, and re-executes the program going down the other path.

条件跳转比常规数据依赖关系更难于流水线执行,因为条件跳转可以更改流水线中的指令流中的下一条指令.这称为控件依赖项,而不是数据依赖项(如add其中两个输入都是其他最近指令的输出).

Conditional jumps are harder for pipelined execution than normal data dependencies, because they can change which instruction should be next in the stream of instructions flowing through the pipeline. This is called a control dependency, as opposed to a data dependency (like an add where both inputs are outputs of other recent instructions).

分支预测器的结果非常好,因为大多数分支趋向于对其方向产生偏见. (通常,大多数循环末尾的分支将分支回到顶部).因此,在大多数情况下,处理器不必退出错误预测的工作.

The branch predictors turn out to be very good, because most branches tend to have bias about their direction. (The branch at the end of most loops, is going to branch back to top, typically). So most of the time the processor doesn't have to back out of wrongly predicted work.

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

If the direction of the branch is highly unpredictable, then the processor will guess wrong about 50% of the time, thus have to back out work. That's expensive.

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

OK, now, one often finds code like this:

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

如果分支预测器猜测正确,那么无论分支走到哪条路,此代码都很快.如果它猜错很多...哎呀.

If the branch predictor guesses right, this code is fast, no matter which way the branch goes. If it guesses wrong a lot... ouch.

因此,条件移动指令.此操作基于条件代码位有条件地移动数据.我们可以重写上面的内容:

Thus the conditional move instruction. This is a move that conditionally moves data, based on the condition code bits. We can rewrite the above:

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

现在,我们没有分支指令,因此也不会因为错误预测而导致处理器撤消所有工作.由于不存在控制依赖性,因此无论movcc是像mov还是nop的行为,都需要提取和解码以下指令.流水线可以保​​持满状态,而无需预测条件并推测性地执行使用register1的指令. (您可以以这种方式构建CPU,但这会违背movcc的目的.)

Now we have no branch instructions, and thus no mispredicts that make the processor undo all the work. Since there is no control dependency, the following instructions need to be fetched and decoded regardless of whether the movcc acts like a mov or nop. The pipeline can stay full without predicting the condition and speculatively executing instructions that use register1. (You could build a CPU that way, but it would defeat the purpose of movcc.)

movcc将控制依赖项转换为数据依赖项. CPU完全像3输入数学指令一样对待它,其输入为EFLAGS及其两个常规"输入(目标寄存器和源寄存器或存储器).在x86上,就乱序执行如何跟踪依赖关系而言,adccmovae相同(如果为CF==0,则为cmovae):输入是CF,并且是两个GP寄存器.输出是目标寄存器.

movcc converts a control dependency into a data dependency. The CPU treats it exactly like a 3-input math instruction, with the inputs being EFLAGS and its two "regular" inputs (dest register and source register-or-memory). On x86, adc is identical to cmovae (mov if CF==0) as far as how out-of-order execution tracks the dependencies: inputs are CF, and both GP registers. Output is the destination register.

对于x86,有 cmovcc

For the x86, there are cmovcc, jcc, and setcc instructions for every condition combination cc. (setcc sets the destination to 0 or 1, according to the condition. So it has a data dependency on the flags, and no other input dependencies.)

这篇关于条件指令(cmov)和跳转指令之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆