3.6 控制
3.6.1 条件码
- CF:进位。无符号溢出
- ZF:零
- SF:符号。负数
- OF:溢出。补码溢出
指令 | 基于 | 描述 |
---|
CMP S1,S2 | S2-S1 | 比较 |
TEST S1,S2 | S1&S2 | 测试 |
3.6.2 访问条件码
指令 | 同义名 | 效果 | 设置条件 |
---|
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 | 低于或相等(无符号<=) |
3.6.3 跳转指令
指令 | 同义名 | 跳转条件 | 描述 |
---|
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) | 小于等于(有符号<=) |
ja Label | jnbe | ~CF&~ZF | 超过(无符号>) |
jae Label | jnb | ~CF | 超过或相等(无符号>=) |
jb Label | jnae | CF | 低于(无符号<) |
jbe Label | jna | CF|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 循环
- 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;
|
- 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;
|
- 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语句
根据一个整数索引值进行多重分支
- 跳转表(开关数量多,值范围小):执行开关语句的时间与开关情况的数量无关
文章作者
lim
上次更新
2024-09-14
(2aae67a)
许可协议
CC BY-NC-ND 4.0