3.6 控制

3.6.1 条件码

  • CF:进位。无符号溢出
  • ZF:零
  • SF:符号。负数
  • OF:溢出。补码溢出
指令基于描述
CMP S1,S2S2-S1比较
TEST S1,S2S1&S2测试

3.6.2 访问条件码

指令同义名效果设置条件
sete DsetzD<——ZF相等/零
setne DsetnzD<——~ZF不等/非零
sets DD<——SF负数
setns DD<——~SF非负数
setg DsetnleD<——~(SF^OF)&~ZF大于(有符号>)
setge DsetnlD<——~(SF^OF)大于等于(有符号>=)
setl DsetngeD<——SF^OF小于(有符号<)
setle DsetngD<——(SF^OF)|ZF小于等于(有符号<=)
seta DsetnbeD<——~CF&~ZF超过(无符号>)
setae DsetnbD<——~CF超过或相等(无符号>=)
setb DsetnaeD<——CF低于(无符号<)
setbe DsetnaD<——CF|ZF低于或相等(无符号<=)

3.6.3 跳转指令

指令同义名跳转条件描述
jmp Label1直接跳转
jmp *Operand1间接跳转
je LabeljzZF相等/零
jne Labeljnz~ZF不相等/非零
js LabelSF负数
jns Label~SF非负数
jg Labeljnle~(SF^OF)&~ZF大于(有符号>)
jge Labeljnl~(SF^OF)大于等于(有符号>=)
jl Labeljnge~SF^OF小于(有符号<)
jle Labeljng(SF^OF)小于等于(有符号<=)
ja Labeljnbe~CF&~ZF超过(无符号>)
jae Labeljnb~CF超过或相等(无符号>=)
jb LabeljnaeCF低于(无符号<)
jbe LabeljnaCF|ZF低于或相等(无符号<=)

3.6.4 跳转指令的编码

  • PC-relative:将目标指令的地址与紧跟在跳转指令后面那条指令的地址之间的差作为编码

3.6.5 用条件控制来实现条件分支

C:

1
2
3
4
if(test-expr)
    then-statement
else
    else-statement

汇编:

1
2
3
4
5
6
7
8
    t = test-expr;
    if(!t)
        goto false;
    then-statement
    goto done;
false:
    else-statement
done:

3.6.6 用条件传送来实现条件分支

  • 使用控制(低效):条件满足时,沿着一条路径执行,不满足时走另一条路径
  • 使用数据(受限):计算一个条件操作的两种结果,然后根据条件是否满足从中选取一个

3.6.7 循环

  1. do-while C:
    1
    2
    3
    
    do
        body-statement
        while(test-expr);
    
    汇编:
    1
    2
    3
    4
    5
    
    loop:
        body-statement
        t = test-expr;
        if(t)
            goto loop;
    
  2. while C:
    1
    2
    
    while(test-expr)
            body-statement
    
    汇编: 方法1:跳转到中间
    1
    2
    3
    4
    5
    6
    7
    
        goto test;
    loop:
        body-statement
    test:
        t = test-expr;
        if(t)
            goto loop;
    
    方法2(较高优化等级编译时):guarded-do(先判断再做do-while)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    t = test-expr;
    if(!t)
        goto done;
    loop:
        body-statement
        t = test-expr;
        if(t)
            goto loop;
    done;
    
  3. for C:
    1
    2
    
    for(init-expr;test-expr;update-expr)
        body-statement
    
    汇编: 方法1:跳转到中间
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    init-expr
    goto test;
    loop:
        body-statement
        update-expr
    test:
        t = test-expr;
        if(t)
            goto loop;
    
    方法2(较高优化等级编译时):guarded-do(先判断再做do-while)
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    init-expr
    t = test-expr;
    if(!t)
        goto done;
    loop:
        body-statement
        update-expr;
        t = test-expr;
        if(t)
            goto loop;
    done;
    

3.6.8 switch语句

根据一个整数索引值进行多重分支

  • 跳转表(开关数量多,值范围小):执行开关语句的时间与开关情况的数量无关