控制指令

条件码

CPU维护一组单个位的条件码寄存器
- CF:进位标志。最近的操作使最高位产生了进位。可用来检查无符号操作的溢出。
- ZF:零标志。最近的操作得出得结果为0。
- SF:符号标志。最仅的操作得到的结果为负数。
- OF:溢出标志。最近的操作导致一补码溢出——正溢出或负溢出。

leaq指令是用来进行地址计算的,不改变任何条件码。

指令 基于 描述
CMP S1, S2 S2 - S1 比较
cmpb 比较字节
cmpw 比较字
cmpl 比较双字
cmpq 比较四字
TEST S1, S2 S1 & S2 测试
testb 测试字节
testw 测试字
testl 测试双字
testq 测试四节

比较和测试指令。这些指令不修改任何寄存器的值,只设置条件码

访问条件码

指令 同义名 效果 设置条件
sete D setz D<—ZF 相等/零
setne D setnz D<—~ZF 不等/非零
sets D D<—SF 负数
setns D D<—~SF 非负数
setg D setnle D<— ~(SF^OF)&~ZF 大于(有符号>)
setge D setnl D<— ~(SF^OF) 大于等于(有符号>=)
setl D setnge D<— SF^OF 小于(有符号<)
setle D setng D<— (SF^OF) ZF
seta D setnbe D<—~CF&~ZF 超过(无符号>)
setae D setnb D<—~CF 超过或相等(无符号>=)
setb D setnae D<—CF 低于(无符号<)
setbe D setna D<—CF|ZF 低于或相等(无符号<=)

SET指令。每条指令根据条件码的某种组合,将一个字节设置为0或者1。有些指令有” 同义名” ,也就是同一条机器指令有别的名字。

跳转指令

指令 同义名 跳转条件 描述
jmp Label 1 直接跳转
jmp *Operand 1 间接跳转
je Label jz ZF 相等/零
jne Label jnz ~ZF 不相等/非零
js Label SF 负数
jns Label ~SF 非负数
jg Label jnle ~(SF^OF)&~ZF 大于(有符号>)
jge Label jnl ~(SF^OF) 大于或等于(有符号>=)
jl Label jnge SF^OF 小于(有符号<)
jle Label jng (SF^OF)|ZF 小于或等于(有符号<=)
ja Label jnbe ~CF&~ZF 超过(无符号>)
jae Label jnb ~CF 超过或相等(无符号>=)
jb Label jnae CF 低于(无符号<)
jbe Label jna CF ZF

jump指令。当跳转条件满足时,这些指令会跳转到一条带标号的目的地。有些指令有” 同义名 “,也就是同一条机器指令的别名

跳转目的地通常用一个标号(Label)指明,类似 “.L1” 。跳转有直接跳转”jmp .L1”或者间接跳转”jmp *%rax”用寄存器和内存中的值作为跳转目标。

跳转指令的编码可以用绝对地址或相对地址,相对地址利用jmp指令后面对应的值+下一条指令的起始地址=跳转目的地,这也方便程序在内存中的移动,最为常用。使用如下例:

   movq  %rdi, %rax
   jmp   .L2
.L3:
   sarq  %rax
.L2:
   testq  %rax, %rax
   jg     .L3
   rep; ret

汇编器产生的 ” .o ” 格式的反汇编版本如下:

0:48 89 f8               mov  %rdi, %rax
3:eb 03                  jmp  8 <loop+0x8>
5:48 d1 f8               sar  %rax
8:48 85 c0               test %rax, %rax
b:7f f8                  jg   5 <loop+0x5>
d:f3 c3                  repz retq
  • 对于jmp 8; 用 0x03(二进制补码)+5 = 0x8 即可得到跳转到8
  • 对于jg 5; 用 0xf8(二进制补码)+0xd = 0x5 即可得到跳转到5

现代使用条件传送来实现条件分支

long absdiff(long x, long y)
{
        long result;
        if(x < y)
                result = y-x;
        else
                result = x-y;
        return result;
}

优化的汇编

long absdiff(long x, long y)
x in %rdi, y in %rsi
absdiff:
        movq    %rsi, %rdx
        subq    %rdi, %rdx      rval = y-x
        movq    %rdi, %rax
        subq    %rsi, %rax      eval = x-y
        cmpq    %rsi, %rdi      compare x:y
        cmovl   %rdx, %rax      if x<y, eval = rval 
        ret                      return eval

以上汇编的实现原理可以使用如下的C语言来解释

long cmovdiff(long x, long y)
{
        long rval = y-x;
        long eval = x-y;
        long ntest = x >= y;
        /* Line below requires
         * single instruction: */
        if(ntest) 
                rval = eval;
        return rval;
}

条件传送指令

指令 同义名 传送条件 描述
cmove S, R cmovz ZF 相等/零
cmovne S, R cmovnz ~ZF 不相等/非零
cmovs S, R SF 负数
cmovns S, R ~SF 非负数
cmovg S, R cmovnle ~(SF^OF)&~ZF 大于(有符号>)
cmovge S, R cmovnl ~(SF^OF) 大于或等于(有符号>=)
cmovl S, R cmovnge SF^OF 小于(有符号<)
cmovle S, R cmovng (SF^OF)|ZF 小于或等于(有符号<=)
cmova S, R cmovnbe ~CF&~ZF 超过(无符号>)
cmovae S, R cmovnb ~CF 超过或相等(无符号>=)
cmovb S, R cmovnae CF 低于(无符号<)
cmovbe S, R cmovna CF|ZF 低于或相等(无符号<=)

条件传送指令。当传送条件满足时,指令把源值S复制到目的R。有些指令是” 同义名” ,即同一条机器指令的不同名字

猜你喜欢

转载自blog.csdn.net/wareric/article/details/80037054
今日推荐