Appearance
题目
减法指令 sub R1,R2,R3 的功能为 (R1)-(R2)→R3,该指令执行后将生成进位/借位标志 CF 和溢出标志 OF。若 (R1)=FFFFFFFFH,(R2)=FFFFFFF0H,则该减法指令执行后,CF 与 OF 分别为( )。
错因
B
把"进位 cout"直接当成 CF 用。减法在硬件上是 ,最高位会有进位 cout = 1。如果直接令 CF = cout,会得到 CF = 1。但减法的 CF 是"借位"含义,约定 CF = (或写作 cout XOR 1):cout = 1 表示无借位 → CF = 0。
C
误判溢出。可能看到 R1、R2 的最高位是 1(看似负数),结果 R3 的最高位是 0(看似正数)——觉得"负 - 负 = 正" 是符号变化就算溢出。但有符号溢出的判定规则是"两正相加得负"或"两负相加得正"(同号相加得反号);同号相减永远不溢出(因为差的绝对值 ≤ 较大者绝对值)。
D
CF 和 OF 都判错。看到 R1、R2 都是 0xFFFF 开头的"大数"就直觉认为既"借位"又"溢出"。但本题真值 R1 = -1、R2 = -16,差 = 15,无借位、无溢出。
总解析
第一步:用补码加法实现减法
减法 在硬件上 = 补 = 。
| 项 | 32 位十六进制 |
|---|---|
| FFFFFFFF | |
| (按位取反) | 0000000F |
| 1 | |
| 求和 | = 0x1_0000_000F |
求和结果是 33 位(最高一位是从第 31 位的进位 cout):
| 位段 | 值 |
|---|---|
| cout(第 32 位进位) | 1 |
| 低 32 位结果 R3 | 0x0000000F = +15 |
与真值核对: ✓
第二步:判定 CF(进位/借位标志)
减法的 CF 约定:CF = (cout = 1 表示加法部分有进位 = 减法没有借位 → CF = 0)。
cout = 1 → CF = 0。
直观理解:CF 表示"减法是否需要借位"。$R_1 = $ 0xFFFFFFFF(无符号 4294967295)和 $R_2 = $ 0xFFFFFFF0(无符号 4294967280),,无需借位 → CF = 0。
第三步:判定 OF(有符号溢出标志)
OF 判定规则:
减法时 取负相加 → 用 与 的符号比较。但更通用的判法是看真值是否超出 [−2³¹, 2³¹−1]:
- = -1, = -16,差 = 15
- 15 在 [−2³¹, 2³¹−1] 范围内 → 不溢出 → OF = 0
也可以用规则:"同号相减结果不变号 → 不可能溢出"。 和 同为负,相减必不溢出。
最终答案是 A(CF=0,OF=0)。
计算过程对照表:
| 维度 | 无符号视角(CF) | 有符号视角(OF) |
|---|---|---|
| 4294967295 | -1 | |
| 4294967280 | -16 | |
| 15(无借位) | 15(在范围内) | |
| 标志 | CF = 0 | OF = 0 |
减法标志位通用规则速记:
| 标志 | 含义 | 计算 |
|---|---|---|
| CF | 减法借位(无符号溢出) | CF = ,cout 来自 最高位进位 |
| OF | 有符号溢出 | 同号相减永不溢出;异号相减可能溢出(看符号是否反) |
| ZF | 结果为零 | 时为 1 |
| SF | 结果符号 | 最高位 |
易错点速查:
- CF 的减法约定:cout = 1 → CF = 0;cout = 0 → CF = 1("无借位 → CF=0")
- 同号相减永不溢出——这是判定 OF 的快速方法
- 看到 0xFFFFFFFF 这种"大数"先按补码读出真值(-1),不要凭无符号大小拍脑袋
编者注(CF 约定):408 教材里 CF 在减法时一律按"借位"理解,CF = 1 表示需要借位(即 无符号比较)。本题 ,所以 CF = 0。部分教材直接令 CF = cout,对减法时不取反;408 真题官方答案均按"借位 = CF" 处理。