Appearance
题目
接上题,R0~R4 为通用寄存器,SEXT 表示按符号扩展,M 中补码除法器,逻辑结构图如下:

机器级代码:
// x 在 R2 中,i 在 R4 中
// 数组 d 的首地址在 R3 中
mov R1,(R3+R4*4) // R1 ← d[i]
scov R1 // {R0,R1} ← SEXT(R1)
idiv R1 // R1<-({R0,R1}/R2)(1) 若执行 idiv 指令时,d[i]=0x87654321,x=0xff,则补码除法器中 R、Q、Y 的初始值分别为多少(用十六进制表示)? 图 b 中哪个部分包含计数器?在补码除法器执行过程中,ALUop 所控制的 ALU 运算有哪几种?
(2) 假设 idiv 执行过程中会检测并触发除法异常,则执行 idiv 指令时,哪些情况下会发生除法异常(要求给出此时 d[i] 和 x 的十六进制机器数)。发生除法异常时,在异常响应过程中,CPU 需要完成哪些操作?
解析
本题考查 补码除法器(恢复余数 / 加减交替法)的初值装载、控制逻辑、ALU 操作种类,以及 除法的两种异常情形 + CPU 异常响应。
补码除法器经典结构:
- R(余数寄存器)+ Q(商 / 被除数低位寄存器) 拼成 64 位被除数;
- Y(除数寄存器) 存除数;
- 控制逻辑 含计数器,控制 32 次迭代;
- 每次迭代左移 R/Q,根据 R 的符号决定 ALU 做 R±Y。
(1) R / Q / Y 初值 + 计数器位置 + ALU 操作 [6 分]
Step 1. 被除数符号扩展。
d[i] = 0x87654321 是 32 位补码,最高位 1 → 负数。scov(符号扩展)把它扩成 64 位补码,高 32 位 = FFFF FFFFH(负数符号扩展高位补 1)。
Step 2. R / Q 初值。
64 位被除数 = :
| 寄存器 | 初值 | 含义 |
|---|---|---|
| R | FFFF FFFFH | 被除数高 32 位(符号扩展后) |
| Q | 8765 4321H | 被除数低 32 位 |
Step 3. Y 初值。
除数 x = 0xFF(题干声明 8 位无符号 0xff)。装入 Y 时按 32 位无符号表示:
易错点: 这里 x 是 unsigned char 类型 / 8 位无符号 → 0xFF = 255 而非 −1。装入 32 位 Y 寄存器时高位补 0,不是符号扩展。如果错按补码扩展,会得到
FFFF FFFFH= −1,这是 (2) 中商溢出的另一情形,结果完全不同。
Step 4. 计数器位置。
图 (b) 中的 控制逻辑模块 包含计数器 C,控制 32 次循环(对应 32 位商的迭代)。
Step 5. ALUop 控制的运算种类。
补码除法采用 加减交替法:
| 情形 | ALU 操作 | 含义 |
|---|---|---|
| 余数与除数同号 | 试减、判断符号 | |
| 余数与除数异号 | 加除数恢复余数 |
ALUop 控制:加法 / 减法 两种。
(2) 除法异常的情形 + CPU 响应 [6 分]
Step 1. 两种异常情形。
情形 A:除数为 0。
任何数除以 0 数学上无意义 → CPU 触发"除以 0 异常"。
- d[i] = 任意值;
- x =
0000 0000H。
情形 B:商溢出。
32 位补码商的合法范围 。当被除数 = 、除数 = 时:
恰好超出最大值 → 商溢出异常。
- d[i] =
8000 0000H(即 ); - x =
FFFF FFFFH(即 )。
编者注(生僻术语): 这是补码 32 位有符号整数除法的唯一商溢出情形。它的根源在于补码范围的不对称——能表示的最小负数 没有对应的正数 。x86 的
idiv指令在这种情况会触发 #DE 异常。
Step 2. CPU 异常响应阶段做的事。
异常响应是硬件自动完成的几步固定动作:
- 关中断——屏蔽其他中断,避免嵌套;
- 保护断点——把当前 PC(异常返回地址)压栈或写入断点寄存器;
- 保护程序状态——把 PSW(程序状态字、含标志位)保存;
- 切换处理器模式——从用户态进入内核态(如果原先在用户态执行);
- 跳转异常处理程序——从中断向量表查得对应服务程序入口,更新 PC。
接下来运行的"异常处理程序"属于软件层面,不再算异常响应阶段。
易错点: 异常响应阶段只做"保存现场 + 切换上下文"这几步硬件动作,不包括 后续异常处理程序中的具体处理(如打印错误、终止进程等)。两者的边界是"PC 跳到异常处理入口"那一刻。