2.2.5 运算方法和运算电路【2011统考真题】


好的,这是一道非常经典的计算机组成原理综合题,它通过一小段C语言代码,全面考察了数据在计算机内部的表示、运算、溢出判断以及运算器的实现原理。
我们来一步一步、详细地解析这道题。
首先,附上题目原文:
题目原文
2.2.5 运算方法和运算电路
(4)【2011统考真题】假定在一个 8 位字长的计算机中运行如下 C 程序段:
unsigned int x = 134;
unsigned int y = 246;
int m = x;
int n = y;
unsigned int z1 = x - y;
unsigned int z2 = x + y;
int k1 = m - n;
int k2 = m + n;
若编译器编译时将 8 个 8 位寄存器 R1~R8 分别分配给变量 x、 y、 m、 n、 z1、 z2、 k1 和 k2。请回答下列问题 (提示: 有符号整数用补码表示)。
- 执行上述程序段后,寄存器 R1、 R5 和 R6 的内容分别是什么 (用十六进制表示)?
- 执行上述程序段后, 变量 m 和 k1 的值分别是多少 (用十进制表示)?
- 上述程序段涉及有符号整数加减、无符号整数加减运算, 这四种运算能否利用同一个加法器辅助电路实现? 简述理由。
- 计算机内部如何判断有符号整数加减运算的结果是否发生溢出? 上述程序段中,哪些有符号整数运算语句的执行结果会发生溢出?
综合解析与分步详解
在开始解题前,我们先做一些基础工作:将初始值 x 和 y 转换为8位二进制和十六进制。
-
unsigned int x = 134;134(十进制) =128 + 4 + 2=1000 0110(二进制)1000 0110(二进制) =86H(十六进制)- 这个值存放在寄存器 R1 中。
-
unsigned int y = 246;246(十进制) =128 + 64 + 32 + 16 + 4 + 2=1111 0110(二进制)1111 0110(二进制) =F6H(十六进制)- 这个值存放在寄存器 R2 中。
问题1分析:计算寄存器内容 (十六进制)
-
寄存器R1的内容:
- R1存放的是变量
x的机器码。根据我们的基础计算,R1的内容就是86H。
- R1存放的是变量
-
寄存器R5的内容 (
z1 = x - y):- 这是一个无符号减法。在计算机中,减法通过加补码实现,即
x - y = x + (-y)的补码。 - x:
1000 0110 - y:
1111 0110 - 求(-y)的补码: 对
y的机器码1111 0110变各位为反码再加1。- 取反:
0000 1001 - 加 1:
0000 1010
- 取反:
- 相加:
1000 0110 (x) + 0000 1010 (-y的补码) -----------1001 0000- 将结果转换为十六进制:
1001->9,0000->0。 - 结论: R5的内容是
90H。
- 这是一个无符号减法。在计算机中,减法通过加补码实现,即
-
寄存器R6的内容 (
z2 = x + y):- 这是一个无符号加法。
- 相加:
1000 0110 (x = 134)+ 1111 0110 (y = 246)----------- (1)0111 1100 (结果 = 380, 产生进位)- 由于寄存器是8位的,最高位的进位
1会被丢弃。存入寄存器的是0111 1100。 - 将结果转换为十六进制:
0111->7,1100->C。 - 结论: R6的内容是
7CH。
问题2分析:计算变量值 (十进制)
-
变量m的值 (
int m = x;):- 这是一个类型转换。
x的机器码1000 0110被赋给有符号整数m。 - 我们需要将
1000 0110这个补码解释为十进制数。 - 识别符号: 最高位是
1,表示这是一个负数。 - 求原码: 对补码
1000 0110再次求补码(取反加1)即可得到其绝对值的原码。- 取反:
0111 1001 - 加 1:
0111 1010
- 取反:
- 计算大小:
0111 1010(二进制) =64 + 32 + 8 + 2=122(十进制)。 - 结论:
m的值是 -122。
- 这是一个类型转换。
-
变量k1的值 (
k1 = m - n;):- 这是一个有符号减法。
m和n的机器码与x和y完全相同。 - 因此,
m - n的二进制运算过程与x - y完全一样,其结果的机器码也是1001 0000。 - 现在我们需要将
1001 0000这个补码解释为十进制数。 - 识别符号: 最高位是
1,是负数。 - 求原码: 对补码
1001 0000求补。- 取反:
0110 1111 - 加 1:
0111 0000
- 取反:
- 计算大小:
0111 0000(二进制) =64 + 32 + 16=112(十进制)。 - 结论:
k1的值是 -112。
- 这是一个有符号减法。
问题3分析:统一加法器实现
- 结论: 能。
- 理由:
- 加法统一: 无论是无符号数还是有符号数(补码),它们的加法运算规则在硬件层面是完全相同的。CPU执行二进制加法时,并不知道这两个数是signed还是unsigned,它只是执行
A+B。结果的解释和溢出判断由后续逻辑决定。 - 减法变加法: 任何减法运算
A - B都可以通过计算A + (-B)来实现。-B就是对B的机器码求补。求补运算可以通过简单的辅助电路(如各位取反器和在加法器最低位设置进位Cin=1)来实现。
- 因此,一个补码加法器,配上一个求补的辅助电路,就可以完成有符号和无符号数的全部加减运算。
- 加法统一: 无论是无符号数还是有符号数(补码),它们的加法运算规则在硬件层面是完全相同的。CPU执行二进制加法时,并不知道这两个数是signed还是unsigned,它只是执行
问题4分析:有符号数溢出判断
-
如何判断溢出?
- 溢出只可能在“同号相加”或“异号相减”时发生。
- 方法一 (符号位法): 两个正数相加,结果为负数,则溢出。两个负数相加,结果为正数,则溢出。
- 方法二 (进位法/硬件法): 检查符号位的进位 (C_s) 和最高数值位的进位 (C_p)。如果
C_s和C_p不相同 (C_s ⊕ C_p = 1),则发生溢出。这是硬件中实际使用的方法。
-
哪些语句会溢出?
-
我们需要检查有符号运算:
k1 = m - n;和k2 = m + n;。 -
分析
k1 = m - n;:m是负数 (-122),n是负数 (-10,因为其机器码1111 0110作为补码解释是-10)。- 运算是
(-122) - (-10) = -112。 - 8位有符号数的表示范围是 [-128, 127]。-112 在此范围内,不溢出。
-
分析
k2 = m + n;:- 运算是
(-122) + (-10) = -132。 - -132 超出了8位有符号数的表示范围 [-128, 127],会发生溢出。
- 用符号位法验证:
m的机器码1000 0110(符号位1,负)n的机器码1111 0110(符号位1,负)m + n的结果机器码是0111 1100(如Q1计算),其符号位是0(正)。- 两个负数相加,结果为正数,判定为溢出。
- 运算是
-
- 结论: 运算语句
k2 = m + n;的执行结果会发生溢出。
