Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

ALU 的状态标志

复习

  1. 第十八章:设计出了简单的 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 有符号
  • 状态标志的生成方法

参考资料

  1. Wikipedia(zh):状态寄存器:状态标志位的详细介绍
  2. 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 国际许可协议进行许可。

封面图

设计师 | 南国微雪