7_条件移动指令

条件移动指令

64 位

int absdiff(int x, int y)
{
    int result;
    if (x > y)
    {
        result = x - y;
    }
    else
    {
        result = y - x;
    }
    return result;
}

如果我们把相同的这段代码, 放到 64 位环境下编译, 生成如下指令 :

absdiff :

;x in %edi, y in %esi

    movl %edi, %eax ; v = x
    movl %esi, %edx ; ve = y
    subl %esi, %eax ; v -= y
    subl %edi, %edx ; ve -= x
    cmpl %esi, %edi ; x : y
    cmovle %edx, %eax   ; v = ve if <=
    ret

注意它减了两次, 也就是说它把 x - y 和 y - x 两个值都算出来了, 无非是一个放到 eax 里面, 一个放到 edx 里面.

然后 cmpl 一下.

然后还用了一个我们不知道的指令. 这条指令是干嘛的呢 ? 我们可以猜测一下, 常规来讲, 生成的汇编代码里面应该会有个类似于条件跳转的东西. 但是现在没有条件跳转指令, 而是有一条 cmovle 这样的指令.

很明显这个是一条条件传送指令.

cmov 就是 conditional move 条件移动

cmovC src, dest, 如果条件 C 成立, 将数据从 src 传送到 dest, 否则什么都不做.

这里的 Condition 就是上面那个大写的 C.

我们这里的就是 le. 这让我们想到了之前 set jmp 指令的那些后缀.

这个意思就是 edi 和 esi 比一比, 如果小于等于的话, 我就把 edx 挪到 eax 里面去, 否则就什么都不做.

我们从执行的角度来看, 条件传送指令效率比一般的条件跳转指令效率高, 因为其控制流可以预测 (就是条件 C 是已知的).