02计算机组成原理-有符号数和无符号数
1.二进制
一个很基础的知识点,计算机中所有的数据都是以二进制的形式存储的。因为在计算机中所有的数都是以高电频和低电频的形式出现的。我们以一高一点的电信号来体现0和1两种不同的状态。
数的二进制表示法对于理解计算机如何进行算术和逻辑运算至关重要:
整数进制转换 正负数的区分
二进制的好处:
1.比较简洁,因为二进制只有两个数字,所有的数字都可以用0或1不同的组合来表示。
2.方便直接映射,因为我们计算机内部的这些硬件基本都是基于电子电路的,所以说计算机内部的逻辑的电路状态可以直接映射到二进制的0或1上,比如一个开启的晶体管可以代表1,一个关闭的晶体管代表0。
3.易于扩展,因为二进制的运算比较简单,所以可以扩展到更复杂的进制。例如二进制扩展到8进制数:100010B==>三位二进制的数对应一位八进制的数,所以100 010即是4 2(一一对应)。
4.内存效率,由于二进制的数表示的非常紧凑,所以存储和传输的时候就比较高效。
信息的最小单位是比特(bit),它只能表示两种状态:0 或 1。
多个比特被组合在一起形成字节(byte),通常一个字节由8个比特组成。 1B=8b多个字节组成一个字。
最低有效位 表示最右边的一位,最高有效位 表示最左边的一位。
MIPS 的字有 32 位 ,如果要存储1011。那就是:
0000 0000 0000 0000 0000 0000 0000 1011(高位补0)
2.整数进制转换
二进制转换为十进制:逐位乘以2的幂次方求和。
二进制转换为八进制:每三位二进制的数看成一个八进制的数,不足三位前面补0
二进制转换为十六进制:每四位二进制的数看成一个八进制的数,不足三位前面补0
十进制转换为x进制:除x取余法
例如:1111011(二进制)转换为十进制
1*20+1*21+0*22+1*23+1*24+1*25+1*26(从右往左,指数从0依次增大)=123
例如:123转换为二进制
123/2=61...1
61/2=30...1
30/2=15...0
15/2=7...1
7/2=3...1
3/2=1...1
1/2=0...1
然后从下向上写余数,类似于进栈出栈。
3.区分正数和负数
前面我们看的二进制的每一项都代表的是数字,所以我们算出来的总是正数,但是在计算机中我们不仅要计算整数还得计算负数。为了区分正数和负数,计算机程序使用了一种称为"符号和幅值"(sign and magnitude)的表示法,即原码:高位(通常是第一位或最左边的位)用作符号位,0表示正数,1表示负数。其余位表示数值的幅值(即绝对值) 。
例如:占8位的二进制,源码表示:
9D: 0000 1001B
-9D:1000 1001B
小补充:数字末尾加个H代表十六进制数,数字末尾加个D代表十进制数,数字末尾加个B代表二进制数,数字末尾加个O代表八进制数。
固定位数(n+1位)的原码范围:
-(2^n^-1), (2^n^-1)
0的原码表示有两种:0000 0000 和 1000 0000,这种不唯一的表示,我们在计算机里不太喜欢。
当运算的结果超出了该数据类型能够表示的范围时,就会发生溢出。(计算机内部一般用补码存储数据,稍后讨论)
通过上述讲解,计算机硬件设计使得其能够高效地执行基于二进制的加法、减法、乘法、除法以及其他逻辑操作,所有这些都直接对应于底层电路中的电子信号的变化。这些基础操作构成了现代计算机计算能力的核心。
4.原码的加减
加减法就和十进制的加减法一样
例:加法:101+ 010:
最右位:1+1=0 → 向中间位进 1(记上进位标记¹)
中间位:0+1 + 进位 1 = 2 → 二进制满 2 进 1,写0 → 向最左位进 1
最左位:1+0 + 进位 1 = 2 → 写0 → 向更高位进 1
例:减法:101-010:
最右位:1 - 0 = 1
中间位:0 - 1 → 不够减,需要向左边的高位借 1。左边的 1 被借走后变成 0,中间位的 0 就变成了 2(因为二进制里借 1 当 2 用),所以 2−1=1
最左位:原来的 1 被借走 1 后剩下 0,再减去 0 → 0 - 0 = 0
注意:源码的加减里面我们是去掉了符号数来进行加减的。
来看下面这个:0110-1010,这个数明显是小的数减去大的数,我们发现最高位应该是0-1,可是左边的数已经不再能往左去借1了,因为已经到了最高位。这时候就出现了问题。所以为了解决这个问题:
在原码加减运算中,对于两个不同符号数的加法(或同符号数的减法),先要比较两个数的绝对值大小,然后用绝对值大的数减去绝对值小的数,最后还要为结果选择合适的符号。
5.原码的优势与劣势
综上:
原码表示法的优点:
原码表示的优点是,与真值的对应关系直观、方便,因此与真值的转换简单,并且用原码
实现乘除运算比较简便。
原码表示法的缺点:
0的表示不唯一,给使用带来不便;加减运算比较复杂,要考虑溢出、负借位等等问题。
为了简化硬件设计并解决这些问题,现代计算机更倾向于使用二进制补码(two's complement)的方式来表示有符号整数。二进制补码不仅解决了正负数的区分问题,还使得加减运算能够通过相同的硬件电路实现,同时有效地处理了溢出情况,并消除了正负零的问题。
6.补码
引一个例子:
在什么情况下15+1=0是正确的。-->15+1对16取余的时候是正确的。
上篇博客提到的寄存器,在MIPS下寄存器存储的代大小是固定的32位,不只是寄存器,包括一些数据通路,比如说从存储器往寄存器里传数据是需要通过线路传的,那这个线路一次性能传多少的数据也是固定的。那也就是说计算机里硬件一次性处理的数据的位数是固定的,假设某一个处理加法的硬件一次性处理硬件的位数是4位,那现在有两个4位的无符号数相加,我们看这么一个例子,1111(15)+0001(1)--->结果确实10000,这个算出来的前提是这个处理加法的硬件一次性只能处理的位数是4位,超过4位,这个硬件会把前面的位数直接丢弃了,就变成了0000(0)。
通过上面我们可以发现,由于位数的限制,计算机硬件天然会对计算出的结果进行一个取余的操作。
既然是模运算,那我们可以利用这个性质来进行一个优化:
现有A B M三个数,有关系:A=B+K*M(K是某个整数)。
A除以M和B除以M的余数是一样的,这种我们称为A和B同余,有了这个同余的关系后我们就可以把加法减法统一起来。
在mod12的运算中:
10-4(mod 12)=10+8(mod 12),想象一个时钟此时时针指向的是10点,顺时针转动8到6点和逆时针转动4到6是一样的。所以在模运算中可以统一起来加法减法,即减一个数等于加上这个同余的数。
同理在计算机中,比如位数是n+1位,那就相当于是mod 2n。所以我们可以转出这样一个补码。
例如刚刚在mod12这个例子上面,我们就可以称-4和8是互补的。
补码定义:对于具有一位符号数和n-1位数字为的二进制整数来说,若补码是
1.正数:与其原码相同,即最高位(符号位)为0,剩余各位表示数值的绝对值。
例如,十进制正数5,在8位二进制补码中的表示为: 0000 0101
2.负数:通过取其绝对值的二进制反码(将所有1变为0,0变为1),然后再加1得到的。
例如,十进制正数5,在8位二进制补码中的表示为: 1111 1011
例如:

注:反码:
1.正数的反码与原码相同。
2.负数的反码是将对应正数(绝对值)的二进制码按位取反。
6.1补码的转换
二进制补码表示的整数转换为十进制数:
1.正数:正常的二进制转十进制的转换规则。
例如,8位二进制补码 0000 1010 表示正数 10。
原码转补码:数值位取反+1
补码转原码:数值位取反 + 1
2.负数:先转换为对应原码(除符号位外,按位取反 再+1),首位是1表示负数,其余按照正常的二进制转十进制的转换规则。
例如,8位二进制补码 1000 1010表示负数-118
因为000 1010-->111 0101-->111 0110-》-118,
n+1位的二进制可以表示的范围:[-(2n), (2n-1)]。比原码表示的范围多了一个。
其中,几个特殊数据的补码表示:
(1)[+0]补=[-0]补=000...000(含符号位共n+1个0),0的补码唯一。
(2)[-2n]补=100...000(n个0),n+1位补码表示的最小整数。
(3)[2n-1]补=011...111(n个1),n+1位补码表示的最大整数。
6.2补码的优势
补码的优势:简化加减运算:补码表示法的优点在于它使得加法和减法运算可以使用相同的硬件电路来实现。在补码表示法中,减法运算可以通过加上减数的补码来实现,从而简化了计算机的设计和实现过程。
无额外的零表示:在补码表示法中,只有一个零,不存在正零和负零的区别。
溢出处理:当两个数相加时,如果发生溢出(最高有效位产生进位),结果仍会落在有效范围内,保持循环不变性,如在8位系统中从最大正值+127加1会自动变成最小负值-128。
关于补码溢出的讨论:。补码表示法的优点之一是它可以很容易地检测到溢出,并且对于加法运算,溢出只可能发生在正溢出(两个正数相加得到负数)或负溢出(两个负数相加得到正数)的情况下。
正溢出:当两个正数相加的结果超过了正数的最大表示范围时,就会发生正溢出。
负溢出:当两个负数相加的结果超过了负数的最小表示范围时,就会发生负溢出。
检测溢出:在补码表示法中,可以通过检查加法运算中的进位来检测溢出。如果两个正数相加时最高位(符号位)产生了进位,或者两个负数相加时最高位没有产生进位,那么就可以确定发生了溢出。
处理溢出:处理溢出的方法取决于特定的应用程序和编程环境。在某些情况下,程序员可能希望捕获溢出并采取相应的措施,如设置错误标志、抛出异常或采取其他错误处理机制。在其他情况下,溢出可能被视为未定义行为,可能导致不可预测的结果。
因为补码表示法具有以上优势:目前大多数现代计算机系统在进行数值的存储和运算时,普遍采用二进制补码表示法。对于整数运算来说,补码是主导的表示法。
值得注意的是,浮点数在计算机内部通常不是以补码形式存储的,而是遵循IEEE 754标准,该标准使用一种不同的编码方案(符号位、指数和尾数)来表示浮点数。这个会在后面的章节讲解。
7.符号扩展
在进行算术运算和逻辑运算时,需要确保操作数的位数一致。那如果位数不一致怎么办?------>符号拓展
符号扩展(Sign Extension)是一种将较短位数的二进制数转换成较长位数二进制数的方法,同时保持数的数值不变。
在符号扩展中,我们观察原始数的最高有效位,即符号位,然后将其复制到新数的高位部分。
例如:
16位的二进制补码数 10000000 00000001拓展为32位:111111111 11111111 10000000 00000001
16位的二进制补码数 00000000 00000001拓展为32位: 00000000 00000000 00000000 00000001
注:
这种方法之所以正确,是因为二进制补码表示的正数实际上在左侧有无限多个0,而负数在左侧有无限多个1,只是为了适应硬件的位数宽度,数的前导位被隐藏了,符号扩展只是简单地恢复了其中一部分。
大概先写这些吧,今天的博客就先写到这,谢谢您的观看。