文章目录
- 线索栏
- 笔记栏
-
- 1. 控制流基础
-
- 1)目标
- 2)机器级机制
- 2. 条件码寄存器
-
- 设置规则
- 3. 比较与测试指令 (CMP & TEST)
- 4. 访问条件码:SET指令
-
- 1)指令格式
- 2)关键后缀规律
- 3)同义名
- 4)SET指令表(图3-14)要点
- 5. 代码示例:comp函数
-
- 关键步骤
- 6. 练习题
-
- 练习题3.13
- 练习题3.14
- 总结栏
线索栏
笔记栏
1. 控制流基础
1)目标
实现C语言的条件语句、循环等。
2)机器级机制
(1)测试数据:通过运算设置条件码(Condition Codes)。 (2)改变控制流:根据条件码,通过JUMP指令跳转到代码的不同部分。
2. 条件码寄存器
CPU维护一组单比特寄存器,描述最近一次算术/逻辑运算的属性:
| CF | 进位标志 | (unsigned)t < (unsigned)a | 无符号溢出(最高位进位) |
| ZF | 零标志 | (t == 0) | 结果为0 |
| SF | 符号标志 | (t < 0) | 结果为负数(符号位为1) |
| OF | 溢出标志 | (a<0 == b<0) && (t<0 != a<0) | 有符号溢出 |
设置规则
(1)LEA指令不改变条件码。 (2)图3-10中大多数指令(ADD, SUB, INC, DEC, 位运算等)都会设置条件码。 (3)移位操作:CF= 最后移出的位;OF=0。
3. 比较与测试指令 (CMP & TEST)
这两条指令只设置条件码,不改变目的寄存器。 
| CMP S1, S2 | 计算 S2 – S1, 据此设置条件码 | 比较。操作数顺序与SUB相反 (CMP b, a比较 a和 b)。 |
| TEST S1, S2 | 计算 S1 & S2, 据此设置条件码 | 测试(通常用于检查位或是否为0)。 |
4. 访问条件码:SET指令
SET指令根据条件码的某种组合,将一个字节(Byte) 设置为0或1,这是访问条件码的第一种方式。
1)指令格式
setX D, 其中X是表示条件组合的后缀,D是单字节寄存器(如%al)或内存地址。
2)关键后缀规律
(1)用于有符号比较:g(greater), l(less), e(equal)等。 (2)用于无符号比较:a(above), b(below), e(equal)等。
3)同义名
同一条机器指令可能有多个名字(如setg≡ setnle)。
4)SET指令表(图3-14)要点

5. 代码示例:comp函数
int comp(data_t a, data_t b) { return a < b; }
// a in %rdi, b in %rsi
comp:
cmpq %rsi, %rdi # 比较 a 和 b (计算 a – b)
setl %al # 若 a < b (有符号),则 %al = 1,否则为0
movzbl %al, %eax # 零扩展%al到%eax (同时清零高4字节)
ret
关键步骤
CMP→ SET→ MOVZ扩展。
6. 练习题
练习题3.13

根据指令序列推断data_t和COMP。 A. cmpl %esi, %di; setl %al cmpl:操作双字(4字节)→ data_t= int。 setl:有符号小于 → COMP= <。
B. cmpw %si, %di; setge %al cmpw:操作字(2字节)→ data_t= short。 setge:有符号大于等于 → COMP= >=。
C. cmpb %sil, %dil; setbe %al cmpb:操作字节(1字节)→ data_t= char。 setbe:无符号低于等于 → COMP= <=(无符号)。
D. cmpq %rsi, %rdi; setne %al cmpq:操作四字(8字节)→ data_t= long或 unsigned long或指针。 setne:不等于(不区分符号)→ COMP= !=。 
练习题3.14
根据TEST和SET推断data_t和TEST。TEST a, a用于测试a本身。 A. testq %rdi, %rdi; setge %al testq:测试8字节 → data_t= long。 setge:有符号非负 → TEST= >=0。
B. testw %di, %di; sete %al testw:测试2字节 → data_t= short。 sete:等于0 → TEST= ==0。
C. testb %dil, %dil; seta %al testb:测试1字节 → data_t= char或 unsigned char。 seta:无符号大于 → 在TEST后,a>0等价于 a != 0→ TEST= !=0(但更准确是>0,对无符号数两者等价)。
D. testl %edi, %edi; setne %al testl:测试4字节 → data_t= int。 setne:不等于0 → TEST= !=0。 
总结栏
本节是理解机器级控制流的基石,引入了条件码系统及如何通过SET指令将其转换为布尔值。
核心启示:计算机通过“先计算状态,后查询状态做出决策”来实现条件分支。条件码系统是这一“状态”的标准化、硬件化的表示。SET指令是连接底层状态与高层逻辑判断的桥梁。掌握条件码和SET指令,是理解后续JUMP(条件跳转)和CMOV(条件传送)指令的基础。


