assembly x86汇编中cmove指令的用途?

a7qyws3x  于 2023-05-23  发布在  其他
关注(0)|答案(4)|浏览(260)

在反汇编一个可执行文件时,我遇到了cmove指令。我已经在互联网上搜索过了,但我只发现这是一个有条件的移动,如果源和目的地相等,就会发生mov。我不明白的是为什么我需要它,因为它不改变操作数。它的目的是什么?

gwo2fgha

gwo2fgha1#

CMOVcc指令不比较源和目标。它们使用来自先前比较(或设置标志的其他操作)的标志,其确定是否应该进行移动。(Intel manual
示例;如果eaxebx相等,则将edx复制到ecx

cmp eax, ebx
cmove ecx, edx

这与以下操作相同:

cmp eax, ebx
jne skip
  mov ecx, edx
skip:
uubf1zoe

uubf1zoe2#

cmov的目的是允许软件(在某些情况下)避免分支。
例如,如果你有这样的代码:

cmp eax,ebx
    jne .l1
    mov eax,edx
.l1:

..,则当现代CPU看到jne分支时,它将猜测是否将采用该分支,然后基于该猜测开始推测性地执行指令。如果猜测是错误的,则会有性能损失,因为CPU必须丢弃任何推测性执行的工作,然后开始获取并执行正确的路径。
对于有条件移动(例如cmove eax,edx),CPU不需要猜测将执行哪个代码,并且避免了错误预测分支的成本。然而,CPU无法知道eax中的值是否会更改,这意味着依赖于条件移动结果的后续指令必须等待,直到条件移动完成(而不是使用假定值进行推测性执行,并且不会停止)。
这意味着,如果分支可以容易地预测,则分支可以更快;并且如果分支不能被容易地预测,则条件移动可以更快。
请注意,条件移动从来不是严格需要的(它总是可以用分支来完成)-它更像是一个可选的优化。

jpfvwuh4

jpfvwuh43#

我已经在互联网上搜索过了,但我只发现这是一个有条件的移动,如果源和目的地相等,就会发生移动。
你的结论是不正确的。
如果前一条指令以满足CMOVcc指令编码指定的条件的方式更改了CPU标志(CF、ZF、OF、SF),则会发生移动。
指令名称中的cc后缀是条件代码的占位符,条件代码可以是A、AE、B、BE、C、E、G、GE、L、LE、NA、NAE、NB、NBE、NC、NE、NG、NGE、NL、NLE、NO、NP、NS、NZ、O、P、PE、PO、S和Z中的任何一个。
在本例中,如果设置了零标志(ZF),CMOVE将执行从源到目标的移动。
我不明白的是为什么我需要它,因为它不改变操作数。
正如我上面解释的,如果满足条件,它确实会改变目的地。
它的目的是什么?
目的是帮助避免条件分支。
避免条件分支的原因是CPU很难预测这些分支是否会被执行。
考虑到x86架构是高度推测性和无序的,它将在它预测的分支开始解码和执行代码,因为在实际需要提高代码执行性能之前就已经采取了。
如果后来发现分支预测不正确,CPU将不得不刷新执行管道并从头开始执行另一个代码路径。
如果这种情况发生在循环或其他关键代码路径中,它会显著降低代码性能,因此您可以使用CMOVcc,以便尽可能避免条件分支。

jc3wubiy

jc3wubiy4#

CMOVcc指令检查EFLAGS寄存器中的一个或多个状态标志(CF、OF、PF、SF和ZF)的状态,并且如果标志处于指定状态(或条件),则执行移动操作。条件码(cc)与每一指令相关联以指示正被测试的条件。如果不满足条件,则不执行移动,并且继续执行CMOVcc指令之后的指令。
这些指令可以将16位或32位值从存储器移动到通用寄存器,或者从一个通用寄存器移动到另一个通用寄存器。不支持8位寄存器操作数的条件移动。
术语“小于”和“大于”用于有符号整数的比较,术语“高于”和“低于”用于无符号整数。
https://wiki.cheatengine.org/index.php?title=Assembler:Commands:CMOVE

相关问题