ALU 的状态标志
复习
- 第十八章:设计出了简单的 ALU,用操作码选择运算
TL;DR
- 运算结果本身之外,ALU 还会“顺手“记下几个特征,叫状态标志
- 常见的四个:零标志 ZF、符号标志 SF、进位标志 CF、溢出标志 OF
- CF 管无符号数,OF 管有符号数,这是最容易混淆、也最关键的一点
正文
为什么还需要标志
ALU 算完 7 + 1 = ?,输出一个 4 位结果 1000。可这到底是 8,还是 -8?
光看结果说不清——同一个二进制串,可能表示不同的值,取决于把它当有符号数还是无符号数。而且运算有没有“越界“、结果是不是零,这些信息后续(比如条件跳转)都要用。
所以 ALU 除了给出结果,还会顺便输出几个 状态标志(Flag),记录这次运算的特征。
四个常见标志
- 零标志(Zero Flag,ZF):结果为 0 时置 1
- 符号标志(Sign Flag,SF):结果为负时置 1(其实就是结果的最高位)
- 进位标志(Carry Flag,CF):产生进位时置 1
- 溢出标志(Overflow Flag,OF):结果超出表示范围时置 1
其中 ZF 和 SF 很好懂,真正绕的是 CF 和 OF。
CF 与 OF:一个管无符号,一个管有符号
记住一句话:
CF 对无符号数运算有意义,OF 对有符号数运算有意义。
为什么?因为“越界“的定义,取决于你怎么看那串二进制:
- 4 位无符号数的范围是 0 ~ 15
- 4 位有符号数的范围是 -8 ~ 7
看三个例子就清楚了。
例一:0111 + 0001 = 1000
- 当作无符号数:7 + 1 = 8,在 0~15 内,没越界 → CF = 0
- 当作有符号数:7 + 1 = 8,超出 -8~7 → OF = 1
例二:0111 + 1001 = (1)0000
- 无符号看:7 + 9 = 16,最高位进位丢失,变成 0 → CF = 1
- 有符号看:7 + (-7) = 0,完全正常 → OF = 0
例三:1000 + 1111 = (1)0111
- 无符号看:8 + 15 = 23,进位丢失,剩下 7 → CF = 1
- 有符号看:(-8) + (-1) = -9,超出 -8~7 → OF = 1
可以看到:同一串结果,无符号和有符号读出来的“是否越界“可以完全不同,所以必须用两个标志分开表示。
标志是怎么生成的
要生成这些标志,只需在 ALU 上再加几个逻辑门:
- 零标志:把结果每一位都“或“起来,若为 0,说明结果全 0(再用非门取反即可)
- 符号标志:直接用结果的最高位
- 进位标志:直接用加法器的进位输出
- 溢出标志:当两个操作数符号相同、但结果符号却和它们不同时,置 1(两个操作数符号相反时,永远不会溢出)
加上这些逻辑,ALU 就完整了:
现代 ALU 还有一些别的标志,比如奇偶标志(Parity Flag,PF),这里就不展开了。这些标志会被送进状态寄存器(PSW),成为后续“条件跳转“的依据——那是讲 CPU 时的事了。
思考题
计算
1010 + 1010(4 位)。分别从无符号和有符号两个角度,判断 CF 和 OF 各是多少。
小结
知识点
- 为什么需要状态标志
- ZF、SF、CF、OF 的含义
- CF 与 OF 的区别:无符号 vs 有符号
- 状态标志的生成方法
参考资料
- Wikipedia(zh):状态寄存器:状态标志位的详细介绍
- Wikipedia(zh):算术溢出:溢出与进位
思考题答案(仅供参考)
1010 + 1010 = (1)0100,丢掉最高进位后结果为 0100。
- 无符号看:10 + 10 = 20,超出 0~15,最高位产生进位 → CF = 1
- 有符号看:(-6) + (-6) = -12,超出 -8~7,且两个操作数同为负、结果却变成正的 → OF = 1
两个数符号相同,所以确实可能溢出;这里结果符号与原符号相反,OF 置 1。
协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
封面图
设计师 | 南国微雪