4.3 标志寄存器与机器状态
执行一条算术指令后,程序通常不仅需要知道保存下来的结果。无符号结果是否过大?结果是否为零?有符号运算是否溢出?8086 把这些事实分别记录在 16 位 FLAGS 标志寄存器的各个位中。
一部分标志描述运算结果,另一部分标志控制处理器行为。
8086 中已定义的标志
| 位 | 名称 | 分组 | 本节含义 |
|---|---|---|---|
| 0 | CF——进位标志 | 状态 | 加法产生最高位进位,或减法需要借位 |
| 2 | PF——奇偶标志 | 状态 | 结果低字节含有偶数个 1 |
| 4 | AF——辅助进位标志 | 状态 | 低半字节边界发生进位或借位 |
| 6 | ZF——零标志 | 状态 | 结果为零 |
| 7 | SF——符号标志 | 状态 | 复制结果的最高有效位 |
| 8 | TF——陷阱标志 | 控制 | 启用单步行为 |
| 9 | IF——中断允许标志 | 控制 | 允许识别可屏蔽外部中断 |
| 10 | DF——方向标志 | 控制 | 决定串操作的变址寄存器递增还是递减 |
| 11 | OF——溢出标志 | 状态 | 有符号结果超出可表示范围 |
原始 8086 FLAGS 字中的其他位是保留位。后来的 x86 处理器扩展了该寄存器,但本教程描述的是 8086 状态。
正在绘制图表…
进位与溢出回答不同问题
同一个位模式既可以表示无符号数,也可以表示有符号数,因此不能把 CF 与 OF 当成同义词。
以 8 位运算 7FH + 01H 为例:
- 按无符号数解释,,仍在 0 到 255 范围内。没有产生第九位进位,所以 CF=0。
- 按二进制补码有符号数解释, 超出了 −128 到 127 的范围。保存的
80H代表 −128,所以 OF=1。
再计算 FFH + 01H。保存的字节是 00H,同时产生第九位进位,因此 CF=1、ZF=1。若按有符号数解释,−1 加 1 等于 0,可以表示,所以 OF=0。
对于减法,当无符号运算需要借位时,8086 会置 CF。按此约定,00H - 01H 得到 FFH,同时 CF=1。
实验 1——让每个算术标志显现出来
修改 8 位操作数并选择 ADD 或 SUB。分析仪会展示完整中间结果以及六个算术标志;不同任务分别突出有符号溢出、无符号进位、零结果和辅助进位。
正在加载交互实验...
检查理解
正在加载概念检查...
正在加载本节练习...
读取其余状态标志
- ZF 判断保存下来的每一位是否都为 0。
- SF 复制保存结果的最高位。8 位运算复制第 7 位,16 位运算复制第 15 位。
- PF 只检查低字节;当其中 1 的数量为偶数时,PF=1。
00000000含有零个 1,而零是偶数,所以 PF=1。
- AF 记录第 3 位与第 4 位之间的进位或借位。它用于支持十进制调整指令;在这里,它也说明即使 CF=0,字内部仍可能发生进位。
并非每条指令都会更新每一个标志。不要假设任何操作之后整个 FLAGS 都会重新计算;指令定义会说明哪些标志被修改、保留或变为未定义。
控制标志改变后续行为
三个控制标志并不描述算术结果:
- DF=0 时,受支持的串指令让 SI 和/或 DI 递增;DF=1 时让它们递减。因此既可以从低地址向高地址遍历,也可以反向遍历。
- IF=1 时,处理器可以在合适的指令边界识别等待中的可屏蔽外部中断;IF=0 会推迟识别。IF 不能屏蔽不可屏蔽中断 NMI,也不是关闭处理器内部异常的总开关。
- TF=1 支持调试:每条指令完成后产生陷阱,让调试器在允许下一条指令之前检查新的机器状态。
正在绘制图表…
上图用于分离概念;精确的优先级与时序由处理器规范定义。初学阶段最重要的规则是:标志属于机器状态,会参与决定下一步行为。
实验 2——控制方向、中断识别与跟踪
向前或向后复制字节,挂起一个可屏蔽中断,并打开或关闭单步跟踪。任务要求你区分“仍在等待的中断”和“已经被处理的中断”。
正在加载交互实验...
检查理解
正在加载概念检查...
正在加载本节练习...
分析标志时,要始终说明运算宽度和数值解释。“发生溢出”并不完整:你需要说明它是无符号进位、有符号溢出,还是内部数字位之间的进位。