文章目录
1. 数制与编码
1.1 进制转换
注意:并不是所有的十进制都能转二进制,只有
1/2
、1/4
、1/8
…才能
1.2 BCD码(采用四位二进制数表示十进制数)
1.3 字符与字符串
1.4 奇偶校验(1位检错,不能纠错)
注意:
- 一种编码方式的码距很重要,用来衡量该方案是否有纠错能力。
- 无论是什么校验,我们默认校验位是不发生跳变的。【做题的时候特别注意】所以一位奇偶校验在检测一位数是100%能检测出错误。
1.5 海明码(2位检错,1位纠错)
上述的海明码还不是实际的海明码,因为其只有检测一位错误的能力,实际上,海明码具有一位纠错,二位检错能力。是因为在其最高位还添加了一个校验位。如下图所示:
注意:
1.6 循环冗余码CRC(只能检错,纠错1位或多位由多项式决定)
注意:
- 在大量数据传送过程中,通常使用CRC校验,而不是奇偶校验或者海明码校验。实际上网络中的数据传输使用的就是CRC
- 在CRC中,接收端检测出错误后,有如下三种纠错方法:
- 请求重发
- 删除数据(触发自动触发)
- 通过余数值自行纠正
- CRC校验可以通过硬件完成。
2. 数的表示与运算
* 数的分类
1. 按小数点的位置分
1. 定点数:平时写的小数,如 6.3
2. 浮点数:科学计数法表示的小数,如 3.14×10^6
2. 按符号分
1. 无符号数
* 注意:通常只有无符号整数,没有无符号小数。
2. 有符号数
2.1 定点数的表示与运算
2.1.1 定点数的表示
无符号定点数很简单,这里不做说明。下面讨论有符号定点数的格式:
2.1.1.1 有符号定点数格式
注意:
- 定点整数和定点小数的默认小数点位置不一样。
- 有符号定点数的整数和小数部分是分开存放的,比如
19.12
,会分成19
和.12
分别单独存放。
2.1.1.2 数值的表示(原码、反码、补码、移码)
1. 原码:真值的绝对值
2. 反码:在原码的基础上,符号位不变,数值部分全部取反
3. 补码:在反码的基础上+1
4. 移码:在补码的基础上,将符号位取反
* 注意:
1. 0和正数的原码、反码、补码相同,移码是符号位取反。其他的按照上面的方式求。【注意,不只是正数,还有0】
2. 原码、反码、补码既能表示`定点整数`也能表示`定点小数`,而移码只能表示`定点整数`。
注意:在求原码的范围时,就是让所有位位1,然后求其值,所以能够取等于。
原码和反码对0
有+0
和-0
两种表达,实际上,+0 = -0 = 0
,只应该有一种表达,所以出现补码,补码的0
只有一种表现形式,空出来的一个位置,用来表示更小的一个负数,即10000000...(符号位1后全为0表示最小负数)
。补码在比较大小时不方便,比较两个数时,应该是从高位到低位进行比较,数大的大。这样补码的数在比较大小时,刚好是个反的,所以,出现了移码。
其实,补码的出现不只是上面的这个原因,实际上原码在进行一个正数与负数进行加操作,即进行减法操作时会很麻烦,使用补码让减法操作变为加法操作,节省硬件成本,(降低ALU复杂度)。
练习:
2.1.2 定点数的运算
2.1.2.1 移位运算
2.1.2.1.1 算术移位(符号位不参与移位)
算术移位是对有符号数进行移位,所以其符号位一定保持不变,也就是符号位不参与运算。右移时补符号位,左移时补0。
注意:
- 如果题目只是说机器码,并没有说是原码、反码、还是补码。则默认为补码。
- 算术左移的条件(补码):最高有效位与原符号位相同。否则会出现严重误差。
可以通过算术移位实现乘法:
2.1.2.1.2 逻辑移位(符号位参与移位)
逻辑移位,等价于对无符号数的移位。
2.1.2.1.3 循环移位(符号位参与移位)
* 循环移位分类
1. 带进位标志位CF的循环移位
2. 不带带进位标志位CF的循环移位
注意:CF在高位的前面
2.1.2.2 加减运算
2.1.2.2.1 原码的加减
因为计算机存放的都是补码,计算时都是根据补码计算的,原码我们只需要会手算就行。
2.1.2.2.2 补码的加减
2.1.2.2.3 溢出的判断
那么如何判断加减后是否溢出?
注意:采用双符号位时,即采用模4补码时,模4补码存储时只需要一个符号位【因为肯定合法】,而在计算加减时可能溢出,在乘除的时候是ALU自动处理,而不需要模4补码。所以模4补码是更容易检测加减而不是乘除的溢出。
2.1.2.2.4 空间扩展的填充的数值
那么出现溢出后应该将空间扩展,比如1B
变为2B
。如何扩展?
2.1.2.3 乘法运算
2.1.2.3.1 原码的一位乘
原码的一位乘,意思是ALU在计算乘法的时候,是拆分成每次计算一位乘实现的。
若数值位有n位,则要进行n次一位乘和n次移位
才能得到结果。
2.1.2.3.2 补码的一位乘
补码一位乘和原码一位乘非常类似,只需要注意如下几个区别就行:
原码一位乘需要的寄存器机器字长为n+1
(单符号)或n+2
(双符号)【n指的是数值位数】;而补码一位乘需要的寄存器机器字长为n+2
(双符号),其中ACC
和X
多的一位是填充符号,而MQ
中多的一位是做辅助位。(计算机中寄存器的机器字长一般是一样的)
其计算过程如下:
2.1.2.3.3 小结
注意:原码和补码一位乘的积有
2N+1
位【要加上1位符号位】
2.1.2.4 除法运算
2.1.2.4.1 原码除法
2.1.2.4.1.1 余数恢复法
注意:
- 乘法中,
X
存放的是被乘数,MQ
中存放的是乘数,最终得到的结果是ACC
存放积的高位,MQ
存放积的低位。- 除法中,
X
存放的是除数,ACC
中存放的是被除数,最终得到的结果是ACC
存放余数,MQ
存放商。
2.1.2.4.1.2 加减交替法
注意:加减交替法只是在最后一步,如果数为负数【不够减】才进行一次余数恢复,其他情况都不恢复。
2.1.2.4.2 补码除法(加减交替法)
2.1.2.4.3 小结
2.1.3 定点数的强制转换
注意:短变长的时候是根据真值的正负扩展的,而不是根据机器数的最高位扩展。
2.1.3 数据的存储与排列
数据的存储有两种模式:
- 大端模式:高位字节存放在低地址处
- 小端模式:高位字节存放在高地址处
现代计算机通常支持按字、半字、按字节寻址,但是最终都会转为按字节编址。如果一台计算机的存储字长为32位,则一个字 = 32bit
,半字 = 16bit
。则访问字转为字节时,是对应二进制数左移2位(32bit/8=2^2, 是2次方所以左移两位)
;同理半字转为字节是左移1位。下面是该例子的示意图:
数据在计算机的排列方式有两种:边界对齐和边界不对齐。
边界不对齐方式在访问一个字或者半字的时候可能需要访问两次存储体:
注意:
3. 边界对齐的方式是以半字为基本单位,凡是不足半字的一律按占半字的空间处理。【牺牲空间换时间】
4. 边界对齐的方式是以字节为基本单位。
2.3 浮点数的表示与运算
2.3.1 浮点数的表示
2.3.1.1 浮点数格式
定点数的格式,导致位数越多存放的数越大,如果是固定的位数,则其表示的数的范围是不变的。那么如果我们想在位数不变的情况下,增加数的表示范围,如何做到?这就涉及到浮点数的表示。
通过上面的浮点数的格式可以看到,如果总的位数不变,我们将尾数的位数变小,阶码的位数相应的会变大,则数的表示范围会变大,但是数的精度会降低。
2.3.1.2 浮点数的规格化
注意:从上图可见,采用规格化浮点数主要是为了增加数据的精度。【本来要舍弃的1,在规格化后被保留了】
这里的规格化与科学计数法不一样,科学计数法是A.BCD * 2^N
, 其中A=1
,而这里的规格化是A=0,B=1
, 是对于小数点后的最高位必为1。后面介绍的IEEE754
标准和科学计数法一样,是A=1
。
注意:
- 判断补码的范围时,我们只需要看
原码范围
+补码1.00000...(全0是否能取到)
- 补码的规格化后,其符号位与最高位一定相反。
2.3.1.3 小结
2.3.2 浮点数标准(IEEE754)
我们知道浮点数分阶码和尾数,而阶码和尾数各占多少位?阶码和尾数具体分别用什么码表示?如果不能统一,那么不同计算机间处理相同的浮点数会存在差异。接下来介绍一种浮点数的统一标准:IEEE754
之前我们介绍的移码是在补码的基础上符号位取反,这是侠义上的移码,即特指偏移值为2^(n-1) 【其中n是机器字长】,将所有的数向数轴右边移动,最左边的-128变为0
, 目的是为了能直接比较数的大小【将移码当作无符号数,然后就可以比较】。下面是广义上的移码:
IEEE754标准:
注意:
IEEE754
规格化的浮点数是指:在平常规格化浮点数的基础上,阶码部分E不全为1和不全为0【也就是去掉偏移值为2^n-1
的两个反常值】,即1<=E<=254
IEEE754
非规格化的浮点数是指:在平常规格化浮点数的基础上,阶码部分E全为1和不全为0【也就是偏移值为2^n-1
的两个反常值】,即E=0 或 E=255
- 上面计算浮点数的真值的公式是针对于规格化的浮点数,才这样计算。
- 虽然
IEEE754
的尾数是用原码表示,但是IEEE754
的两个数相加减的时候还是用补码进行运算,算完后再转会来。
规格化的浮点数的最小值和最大值的范围如上图所示,那么在同样的IEEE75
标准下能不能表示更大或更小的浮点数?
实际上是能的,需要用到非规格化的浮点数:
2.3.3 浮点数的运算
2.3.3.1 浮点数的加减运算
浮点数的加减运算步骤:
- 对阶:阶数小的向阶数大的对齐。【注意阶码-1时同时将尾数算术右移1位】
- 尾数加减:注意是用补码加减【如果不是补码可以先转补码,算完后再转回来,比如
IEEE754
标准就需要这样处理】 - 规格化:和平常的浮点数规格化一样。如果是补码则
[S]补=00.1xxxxx 或 S]补=11.0xxxxx
【注意尾数规格时,阶码也变化】
如果加减的数符号位不一样,表示溢出,但是此时的溢出是可以挽救的,则都需要右规
,且符号位改为本应该得到的那一位。【只需要右规一次】- 如果加减后得到
01.xxxx
, 则为00.1xxxx
- 如果加减后得到
10.xxxx
, 则为11.0xxxx
- 如果加减后得到
- 舍入:有恒置“1”法 和 “0”舍"1"入法 两种
- 判断溢出:由阶码的符号决定,如果阶码的双符号位不同,则表示溢出。
- 为
01
时,即阶码大于最大阶码,表示上溢,进入中断。 - 为
10
时,即阶码小于最大阶码,表示下溢,按机器0处理。 - 若尾数全为
0
,也按机器0处理。
- 为
注意:
- 左规:当浮点数运算的结果为非规格化时,要进行规格化处理,将尾数算术左移一位,阶码减1。【左规可能要进行多次】
- 右规:当浮点数运算的结果尾数溢出(双符号位不同时),将低位符号位和尾数一起算术右移1位,然后低位符号位补高位符号位的数,再阶码加1。【右归只需要进行一次】
注意:如果数符为1位,在对阶后进行加减的时候,在ALU中会扩展为双符号位进行计算。所以,在做题计算时,要采用两位符号位。
二进制浮点数计算步骤中的舍入,常用两种方法:
2.3.3.2 (C语言)浮点数强制类型转换
2.3.3.3 小结
3. 算术逻辑单元(ALU)
3.1 算术逻辑单元
3.1.1 逻辑元件
3.1.2 一位全加器
3.1.3 小结
3.2 改进的算术逻辑单元(并行进位的并行加法器)
注意:
- 并行进位,又叫先行进位或者同时进位
- 4个
SN74181
可以组成一个16位的组内并行,组件串行的16位ALU【一个SN74181是并行4位】- 4个
SN74181
和1个SN74182
可以组成一个16位的组内并行,组件并行的16位ALU【一个SN74182是并行16位】
4. 补充
1. 在做题时,如果没有说明机器字长,则默认为32位。而32位的int和long都占4个字节。
2. 发生溢出
1. 【x】移 到 【-x】移 的溢出:只需要找到真值为-128的这个数,其相反数是128,是无法表示的。 P53 40
2. 补码 + 移码 的溢出:用双符号位判断 P53 44
3. unsigned int x = 134;
unsigned int y = 246;
unsigned int z = x - y;
设机器码为补码形式,字长为8为,求z的机器码(用16进制表示)
[x]补 = 1000 0110B [y]补 = 1111 0110B [-y]补 = 0000 1010B
[x - y]补 = 1001 0000B = 90H
4. 浮点数的阶码和尾数均采用补码表示,且位数分别为5和7。 是含符号位,即 00000 0000000
5. 变形补码:用两个符号位,其余与补码相同。
6. 相同的浮点数格式,基数越大,所能表示的数的范围越大,但是其精度也越低。
7. 设浮点数的基数为8,尾数用模4补码表示,则 00.000111不合法,11.111101也不合法。原因:小数点后紧接着3位做1位8进制数,所以00.000xxx和11.111xxx不合法。
8. 采用浮点数主要是为了增加数的表示范围。
采用规格化浮点数主要是为了增加数据的精度。
9. 舍入是浮点数的概念,定点数没有该概念。用到舍入只有两种情况:
1. 右规格化
2. 对阶
10. 几个命题:
1. 对阶操作不会引起阶码上溢或下溢。 对,因为小向大对齐,而大必然没有溢出
2. 右规和尾数舍入都可能引起阶码上溢出 正确
3. 左规时可能引起阶码下溢 正确
4. 尾数溢出时结果不一定溢出。 正确,最终是看阶码是否溢出,尾数的溢出可以牺牲精度来挽救。
11. ALU是由组合逻辑电路组成,最基本的部件是并行加法器。
12. 若计算机的机器字长足够长,能准确的表示每个数吗?
能精准的表示每个整数,但是并不能精准的表示每个小数,因为二进制小数只能用1/(2^n)的组合表示。
13. 在计算机的内部数值全是二进制数吗?
* 计算机内数值的表示有两大类:
1. 二进制
2. 二进制编码的十进制数,比如8421编码
* 所以,计算机中的数值数据并不只是有二进制,但是其编码只能为二进制编码。