Assembly: CMOVB instruction in Intel x86-64 assembly

Viewed 1826

I'm a little confused about what "cmovb" does in this assembly code

leal   (%rsi, %rsi), %eax  // %eax <- %rsi + %rsi
cmpl   %esi, %edi          // compare %edi and %esi
cmovb  %edi, %eax
ret

and the C code for this is:

int foo(unsigned int a, unsigned int b)
{
    if(a < b) 
        return a;
    else
        return 2*b;
}

Can anyone help me understand how cmovb works here?

2 Answers

C MOV B = Conditional MOVe if Below (Carry Flag Set). It literally does what it says, if the condition is met then move. The condition is a<b and the value moved is 2*b

The ABI stores the return value in %edi, so it first stores a and then conditionally overwrites it with 2*b.

Like Jester commented to the question, the cmov* family of instructions are conditional moves, paired via the flags register with a previous (comparison) operation.

You can use for example the Intel documentation as a reference for the x86-64/AMD64 instruction set. The conditional move instructions are shown on page 172 of the combined volume.

cmovb, cmovnae, and cmovc all perform the same way: If the carry flag is set, they move the source operand to the destination operand. Otherwise they do nothing.

If we then look at the preceding instructions that affect flags, we'll see that the cmp instruction (the l suffix is part of AT&T syntax, and means the arguments are "longs") changes the set of flags depending on the difference between the two arguments. In particular, if the second is smaller than the first (in AT&T syntax), the carry flag is set, otherwise the carry flag is cleared; just as if a subtraction was performed without storing the result anywhere. (The cmp instruction affects other flags as well, but they are ignored by the code.)

Related