21

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?

S.S. Anne
  • 14,415
  • 7
  • 35
  • 68
maluz
  • 245
  • 1
  • 2
  • 10

3 Answers3

48

The CMOVcc instructions don't compare the source and destination. They use the flags from a previous comparison (or other operation that sets the flags) which determines if the move should be done or not. (Intel manual)

Example; this copies edx to ecx if eax and ebx are equal:

cmp eax, ebx
cmove ecx, edx

This does the same as:

cmp eax, ebx
jne skip
  mov ecx, edx
skip:
Peter Cordes
  • 286,368
  • 41
  • 520
  • 731
Guffa
  • 666,277
  • 106
  • 705
  • 986
  • 1
    @Guffa indeed it does the same thing, but the first one does not care about branch prediction failures. – Eugene May 03 '19 at 11:43
  • 5
    Important point: `cmov` with a memory source operand like `cmoveq eax, [edx]` is an *unconditional* load that feeds an ALU select operation. It will [fault on a bad address](https://stackoverflow.com/questions/54050188/hard-to-debug-segv-due-to-skipped-cmov-from-out-of-bounds-memory) even if the condition is false. And the point of `cmov` is to have a data dependency instead of a control dependency (branch misprediction is possible). – Peter Cordes May 26 '19 at 03:52
  • (typo in previous comment: it's `cmove` not `cmoveq`. Perhaps I was thinking of ARM's condition names that are always 2 letters long, like `eq` for equal, unlike x86's `e` for equal) – Peter Cordes Apr 30 '21 at 11:29
12

The purpose of cmov is to allow software (in some cases) to avoid a branch.

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.

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).

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.

Brendan
  • 31,872
  • 2
  • 33
  • 57
1

The CMOVcc instructions check the state of one or more of the status flags in the EFLAGS register (CF, OF, PF, SF, and ZF) and perform a move operation if the flags are in a specified state (or condition). A condition code (cc) is associated with each instruction to indicate the condition being tested for. If the condition is not satisfied, a move is not performed and execution continues with the instruction following the CMOVcc instruction.

These instructions can move a 16- or 32-bit value from memory to a general-purpose register or from one general-purpose register to another. Conditional moves of 8-bit register operands are not supported.

The terms "less" and "greater" are used for comparisons of signed integers and the terms "above" and "below" are used for unsigned integers.

https://wiki.cheatengine.org/index.php?title=Assembler:Commands:CMOVE

Peter
  • 823
  • 9
  • 17