When disassembling an executable I encountered the cmove
instruction. I've already searched on the Internet but I've only found that it's a conditional move, and if the source and destination are equal a mov
occurs. What I don't understand yet is why I need it, since it doesn't change the operands. What is its purpose?
在反汇编可执行文件时,我遇到了cmove指令。我已经在互联网上搜索了但我发现这是一个有条件的移动,如果源和目的地相等则会发生一个mov。我还不明白为什么我需要它,因为它不会改变操作数。它的目的是什么?
2 个解决方案
#1
The CMOVcc
instructions doesn't compare the source and destination. It uses the flags from a previous comparison (or other operation that sets the flags) which determines if the move should be done or not.
CMOVcc指令不会比较源和目标。它使用先前比较的标志(或设置标志的其他操作)来确定是否应该进行移动。
Example; this copies edx
to ecx
if eax
and ebx
are equal:
例;如果eax和ebx相等,则将edx复制到ecx:
cmp eax, ebx
cmoveq ecx, edx
This does the same as:
这与以下相同:
cmp eax, ebx
jne skip
mov ecx, edx
skip:
#2
The purpose of cmov
is to allow software (in some cases) to avoid a branch.
cmov的目的是允许软件(在某些情况下)避免分支。
For example, if you have this code:
例如,如果您有此代码:
cmp eax,ebx
jne .l1
mov eax,edx
.l1:
..then when a modern CPU sees the jne
branch it will take a guess about whether the branch will be taken or not taken, and then start speculatively executing instructions based on the guess. If the guess is wrong there's a performance penalty, because the CPU has to discard any speculatively executed work and then start fetching and executing the correct path.
然后,当现代CPU看到jne分支时,它会猜测是否采用分支,然后根据猜测开始推测性地执行指令。如果猜测错误则会导致性能下降,因为CPU必须丢弃任何推测性执行的工作,然后开始获取并执行正确的路径。
For a conditional move (e.g. cmove eax,edx
) the CPU doesn't need to guess which code will be executed and the cost of a mispredicted branch is avoided. However, the CPU can't know if the value in eax
will change or not, which means that later instructions that depend on the results of the conditional move have to wait until the conditional move completes (instead of being speculatively executed with an assumed value and not stalling).
对于条件移动(例如cmove eax,edx),CPU不需要猜测将执行哪个代码并且避免错误预测分支的成本。但是,CPU无法知道eax中的值是否会发生变化,这意味着后来依赖于条件移动结果的指令必须等到条件移动完成(而不是以假定值推测性地执行)而不是拖延)。
This means that if the branch can be easily predicted a branch can be faster; and if the branch can't be easily predicted the condition move can be faster.
这意味着如果可以容易地预测分支,则分支可以更快;如果不能轻易预测分支,则条件移动可以更快。
Note that a conditional move is never strictly needed (it can always be done with a branch instead) - it's more like an optional optimization.
请注意,从不严格需要条件移动(它总是可以用分支来完成) - 它更像是一个可选的优化。
#1
The CMOVcc
instructions doesn't compare the source and destination. It uses the flags from a previous comparison (or other operation that sets the flags) which determines if the move should be done or not.
CMOVcc指令不会比较源和目标。它使用先前比较的标志(或设置标志的其他操作)来确定是否应该进行移动。
Example; this copies edx
to ecx
if eax
and ebx
are equal:
例;如果eax和ebx相等,则将edx复制到ecx:
cmp eax, ebx
cmoveq ecx, edx
This does the same as:
这与以下相同:
cmp eax, ebx
jne skip
mov ecx, edx
skip:
#2
The purpose of cmov
is to allow software (in some cases) to avoid a branch.
cmov的目的是允许软件(在某些情况下)避免分支。
For example, if you have this code:
例如,如果您有此代码:
cmp eax,ebx
jne .l1
mov eax,edx
.l1:
..then when a modern CPU sees the jne
branch it will take a guess about whether the branch will be taken or not taken, and then start speculatively executing instructions based on the guess. If the guess is wrong there's a performance penalty, because the CPU has to discard any speculatively executed work and then start fetching and executing the correct path.
然后,当现代CPU看到jne分支时,它会猜测是否采用分支,然后根据猜测开始推测性地执行指令。如果猜测错误则会导致性能下降,因为CPU必须丢弃任何推测性执行的工作,然后开始获取并执行正确的路径。
For a conditional move (e.g. cmove eax,edx
) the CPU doesn't need to guess which code will be executed and the cost of a mispredicted branch is avoided. However, the CPU can't know if the value in eax
will change or not, which means that later instructions that depend on the results of the conditional move have to wait until the conditional move completes (instead of being speculatively executed with an assumed value and not stalling).
对于条件移动(例如cmove eax,edx),CPU不需要猜测将执行哪个代码并且避免错误预测分支的成本。但是,CPU无法知道eax中的值是否会发生变化,这意味着后来依赖于条件移动结果的指令必须等到条件移动完成(而不是以假定值推测性地执行)而不是拖延)。
This means that if the branch can be easily predicted a branch can be faster; and if the branch can't be easily predicted the condition move can be faster.
这意味着如果可以容易地预测分支,则分支可以更快;如果不能轻易预测分支,则条件移动可以更快。
Note that a conditional move is never strictly needed (it can always be done with a branch instead) - it's more like an optional optimization.
请注意,从不严格需要条件移动(它总是可以用分支来完成) - 它更像是一个可选的优化。