假定在一个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。请回答下列问题。(提示:带符号整数用补码表示)
(1)执行上述程序段后,寄存器R1、R5和R6的内容分别是什么?(用十六进制表示)
(2)执行上述程序段后,变量m和k1的值分别是什么?(用十进制表示)
(3)上述程序段涉及带符号整数加/减、无符号整数加/减运算,这四种运算能否利用同一个加法器及辅助电路实现?简述理由。
(4)计算机内部如何判断带符号整数加/减运算的结果是否发生溢出?上述程序段中,哪些带符号整数运算语句的执行结果会发生溢出?
这是我整理的答案(主要还是说一下前面的问题)
解:x,y变量值和对应寄存器如下,:
x R1 1000 0110 134
y R2 1111 0110 246
m,n变量值和对应寄存器如下,:
m R3 1000 0110 -122
n R4 1111 0110 -10
说明:将原来的无符号数当作有符号数的补码,
z1,z2变量:
z1(R5) = 1000 0110 – 1111 0110 = 1001 0000 运算时最高位需要借位。
z2(R6) = 1000 0110 + 1111 0110 = 0111 1100 运算时最高位会产生进位
说明: 这是做无符号运算,无符号运算只要有进位或借位就是溢出。
k1,k2变量:
k1(R7) = 1000 0110 – 1111 0110 = 1000 0110 + 0000 1010 = 1001 0000 运算时最高位有借位,就是C=1。最高位和C相同,没有溢出。
k2(R8) = 1000 0110 + 1111 0110 = 0111 1100 运算时最高位会产生进位,即C=1,最高位和C不同,产生溢出。
解答:
(1) R1=0x86 R5=0x90 R6=0x7C
(2) m=-122 k1=-112
(3) 有符号和无符号数可以用同一个硬件加法器,有符号和无符号加法做的操作时一样的,仅仅是溢出判断不同。
(4) 对于无符号数,只要有进位或借位,就是溢出了。 对于有符号数,需要进位/借位与符号位综合考虑,才能判断结果是否溢出。
这里主要是看一下m,n变量值和对应寄存器(如果第二问不会就好好读读,如果会了当我没说)
①int类型和unsigned int类型的差别。unsigned int类型比int类型的容量大是因为,unsigned int是无符号类型的,所以最高位不表示正负,而int类型的最高位是表示正负的,1表示负数,0表示正数。
②计算机中负数的存储方式——其补码。在计算机中,负数存储的方式都是以其其补码形式储存,例如:6在计算机的存储形式是0000 0000 0000 0110(32位计算机中),而-6是1000 0000 0000 0110 (32位机下)(最高位是符号位),补码也就是1111 1111 1111 1010(32位计算机中),补码=原码取反+1。
③赋值一个负数给unsigned int类型的变量,它的意思就是将-6这个数的补码形式(1111 1111 1111 1010(32位机下))形式存到一个叫b的空间中,下次我读取这个数的时候,是使用b这个名字,按照b这个名字的类型来读取的,所以当b是unsigned int类型的时候,就不考虑最高位是符号位,则b = 1111 1111 1111 1010(32位机下)(因为是无符号),当b是int类型的时候,考虑最高位是符号位(1为负数,0为正数),当发现是1的时候也就是负数的时候,计算机会把它转换成为原码从而读出是-6。所以一个变量的类型是决定读取这个变量存储的数的方式。
④隐式转换。当unsigned int类型与int类型运算时,如果没有指出转换的类型,它会进行“隐式转换”转换为unsigned int类型,也可以记住,不同类型进行运算时,没指出转换的类型时,它会往容量大的那总类型转换,因为这样可以更加容易避免溢出嘛。