diff --git a/Computer-Organization/1-data-representation-and-operation.md b/Computer-Organization/1-data-representation-and-operation.md index afe6a13..ad391a1 100644 --- a/Computer-Organization/1-data-representation-and-operation.md +++ b/Computer-Organization/1-data-representation-and-operation.md @@ -343,15 +343,230 @@ k|2|3|4|5|6|7 + 如-24-124=11,110 1000+11,000 0100=10,110 1100=108。下溢。 + 如15+124=00,000 1111+00,111 1100=01,000 1011=-117。上溢。 + 实际存储时只存储一个符号位,运算时会复制一个符号位。 -+ 符号扩展 ++ 符号扩展:防止溢出的一个方法就是将短数据扩展为长数据。 + + 整数扩展,在原符号位和数值位中间添加新位,正数都填充0,对于负数: + + 原码:扩展补0。 + + 反码:扩展补1。 + + 补码:扩展补1。 + + 小数扩展,在最后面添加新位,正数都填充0,对于负数: + + 原码:扩展补0。 + + 反码:扩展补1。 + + 补码:扩展补0。 #### 乘法运算 +对于原码的乘数运算可以参考十进制的乘数运算,将乘数一位一位的乘被乘数然后再全部相加得到的就是答案。而使用二进制的一位位乘法显然比十进制的一位位乘更简单。 + +##### 原码一位乘法 + +一般使用原码一位乘法,即每次只乘一位的数据。 + +在原码乘法时,可以先符号位单独处理,将两个符号进行异或操作,得到的结果就是最后的结果的符号。然后对数据的绝对值(去除符号位)进行一位位的乘法(位积)然后相加。 + +在运算器的组成时出现一个表格,说明在进行乘运算时,ACC保存乘积高位,MQ保存乘数与乘积低位,X保存被乘数。 + +原码一位乘法机器实现时就是按照这种方式计算: + +1. 字长若为n+1位,则ACC、MQ、X全部初始化为n位,将被乘数的绝对值放入X中,MQ放入乘数的绝对值,ACC初始化为全0。 +2. 将MQ的最右边的一位当做当前乘运算位,让其进行乘运算,运算规则是,若当前位是1,则ACC加上被乘数,即ACC+=X,若当前位是0,则ACC加上0(保持不变,跳过)。 +3. 将ACC和MQ的数据连接在一起,全部逻辑右移一位,ACC数据高位补0,ACC最后一个低位移到MQ的最高位。将MQ的最后一位抛弃。若是第i轮逻辑右移,则MQ的前i位是结果的后i个低位值。 +4. 从步骤二开始重复,字长若为n+1位,则重复n次,直到MQ的最后一位是符号位,则停止计算。此时ACC的全部和MQ的前n位都是结果。 +5. 定点小数的小数位隐藏在符号位后面第一位,定点正数的小数位隐藏在MQ符号位的前一位。 +6. 将两个符号位的异或结果赋值给积最高位。 + +**例题** 设机器字长为n+1=5位(含1位符号位),其中x的原码为1.1101,y的原码为0.1011,采用原码一位乘法求xy。 + +其中x就是-0.1101,而y就是+0.1011。先抛去符号位,就得到01101和01011两个数据。 + +将MQ、ACC、X都初始化为五位存储单元。X放入被乘数01101,MQ放入乘数01011,ACC为00000。 + +运算器结构:ACC与MQ相连,数据流是双向的,ACC与ALU相连,数据流是双向的,X的数据流向ALU。 + +此时MQ=01011,作为乘法单位的最后位为1,所以ACC+=X,从而=00000+01101=01101,这就是第一个的位积。 + +由于按照乘法规则,第二个位积计算时需要错位相加,计算机的处理方式是ACC和MQ的数据连在一起,全部逻辑右移一位(左边补0)。 + +所以ACC的数据由01101变为00110,最后的1移到MQ最高位,MQ由01011变为10101,最后的一位1溢出被抛弃,代表这一位的位积已经计算并相加完成,所以不用管了。此时结果的高位还在ACC中,而结果的低位从ACC移到了MQ中,在MQ的低位也不参与后面的运算,所以也不用管了。 + +然后计算下一个最低位的位积,此时MQ的最低位还是1,所以ACC+=X=00110+01101=10011。 + +同样计算完后再错位,进行逻辑右移,ACC由10011变成了01001,MQ由10101变成了11010,最低位的1被抛弃,此时MQ中已经有两个结果最低位。 + +此时MQ最低位为0,所以ACC保持不变,再逻辑右移一位,ACC由01001变为00100,MQ由11010变为11101,抛弃一位0,MQ有三个结果最低位。 + +此时MQ最低位为1,则ACC+=X=00100+01101=10001。 + +同样计算完后再错位,进行逻辑右移,ACC由10001变成了01000,MQ由11101变成了11110,最低位的1被抛弃,此时MQ中已经有四个结果最低位,此时MQ最低位是代表符号的0不参与运算。此时计算已经结束。 + +小数的小数点隐藏在第一位的后面,所以此时结果在ACC和MQ的前四位中,即0.10001111。最后加上符号异或结果,得到1.10001111。 + +##### 补码一位乘法 + +对于补码的乘法运算的逻辑也跟原码的类似,补码的计算就是使用Booth算法实现: + + |原码|补码 +:----:|:--:|:--: +计算流程|n轮加法、移位|n轮加法、移位,最后进行一次加法 +加法的值|+0、+x的原码|+0、+x的补码、+(-x)的补码 +判断加值的根据|MQ的最低位|MQ的最低位、辅助位 +判断关系|MQ的最低位=1时,ACC+x的原码;MQ的最低位=0时,ACC不变|辅助位-MQ中最低位=1时,(ACC)+x的补码;辅助位-MQ中最低位=0时,ACC不变;辅助位-MQ中最低位=-1时,ACC+(-x)的补码 +移位类型|逻辑右移|算术右移 +符号位|不参与运算|参与运算 + +辅助位其实就是在MQ最后再加上一位,辅助位初始为0。每次右移会使MQ的最低位顶替原本的辅助位(事实上MQ共n+2位)。 + +为了保证统一,所以ACC和X都会增加一位,变成n+2位,多出来的一位就可以实现双符号位补码运算,二MQ还是用原理的单符号位。 + +为了加快运算会有辅助电路实现(-x)的补码的运算。 + +最后一次不需要移位直接根据辅助位和MQ最后一位判断进行相加。从而让乘数的符号位也参数运算中来确定最后结果的符号。 + #### 除法运算 +进行除法操作时,都是为了找到一位能让商乘除数能最大即余数最小但大于0的值。若除数被除数都是小数,可以同时乘一个数变成整数再运算。 + +所以可以忽略小数点,每确定一位商进行一次减法,若机器字长为n位,则得到n-1位余数,在余数末尾补0,再确定下一位商0或1,直到确定n位商即可停止。 + +在运算器的组成时出现一个表格,说明在进行除运算时,ACC保存被除数和余数,MQ保存商,X保存除数。 + +##### 原码恢复余数法 + +原码使用恢复余数法进行除运算: + +1. 字长若为n+1位,则ACC、MQ、X全部初始化为n位,将被除数的绝对值放入ACC中,X放入除数的绝对值,MQ初始化为全0。 +2. 将MQ的最右边的一位当做当前除运算位,让其进行除运算,运算规则是,默认商1,ACC-=X,即x的补码要加上除数的绝对值的负值的补码(减法都由补码的加法实现),判断是否有误。若结果高位为0则无误,高位为1则有误,错误则商改为0,并恢复余数,ACC加上X中除数的补码。 +3. 将ACC和MQ的数据连接在一起,全部逻辑左移一位,MQ数据低位补0,MQ最高位的0移到ACC的最低位。将ACC的最高一位抛弃。若是第i轮逻辑左移,则MQ的后i位是当前计算的商的结果。 +4. 从步骤二开始重复,字长若为n+1位,则左移n次,上商n+1次,直到MQ中全部是计算结果,则停止计算。此时MQ中保存商,ACC中保存左移n位的余数值,真正的余数应该是结果再乘上2的-n次方。 +5. 定点小数的小数位隐藏在符号位后面第一位,定点正数的小数位隐藏在最后一位后。 +6. 将两个符号位的异或结果赋值给商最高位。 + +**例题** 设机器字长为5位(含一位符号位),x=0.1011,y=0.1101,采用原码恢复余数法求x/y。 + +其中x就是+0.1011,而y就是+0.1101。先抛去符号位,就得到01011和01101两个数据。然后求出y绝对值的补码:01101和-y绝对值的补码:10011。 + +将MQ、ACC、X都初始化为五位存储单元。将被除数01011放入ACC中,将除数01101放入X中,商初始化为00000。 + +手算时每位商取0/1是通过判断当前余数和除数的大小确定的。而机器实现时就要通过ALU判断是ACC中的数更大还是X中的数更大,如果ACC的更大就商1,若X的更大就商0。 + +第一位默认商1,ACC-=X,ACC的01011和X的10011(X实际值的负值的补码)输入ALU进行加操作01011+10011=11110,返回给ACC,此时发现代表符号的最高位为1,代表出现了负数,就表明之前的商出错了,所以重新确定商为0,ACC要恢复余数,从而再加上y的补码:11110+01101=01011。 + +第一位的商计算完后需要进行计算,错位相除,所以同乘法一样,ACC和MQ的值都要逻辑左移一位,低位补0,所以MQ由00000还是变为00000,MQ的最高位的0移到ACC最低为,ACC最高位丢弃,由01011变成10110。 + +然后第二位默认商1,同样ACC-=X,10110+10011=01001,将这个值赋给ACC,发现符号位为0,代表正,商就没有问题,MQ为00001。 + +再次逻辑左移一位,MQ由00001变为00010,ACC由01001变为10010。 + +第三位默认商1,同样ACC-=X,10010+10011=00101,商没有问题,MQ为00011。 + +再次逻辑左移一位,MQ由00011变为00110,ACC由00101变为01010。 + +第四位默认商1,同样ACC-=X,01010+10011=11101,高位为1,商应该为0,MQ变为00110,ACC恢复余数:11101+01101=01010。 + +再次逻辑左移一位,MQ由00110变为01100,ACC由01010变为10100。 + +第五位默认商1,同样ACC-=X,10100+10011=00111,高位为0,商没有问题,MQ为01101。 + +此时计算结束,商为01101,余数为00111。 + +##### 原码加减交替法 + +因为恢复余数很麻烦,所以会考虑是否不用恢复余数,直接进行运算得到后面的结果。 + +假如令原始值为x,原始值加上-y绝对值的补码结果为a,y绝对值的补码为b,按恢复余数法,a这个余数是一个负值,所以要加上b即a+b变成原始值a+b=x,这时候商0,然后计算下一个商,余数a+b左移一位,即(a+b)×2=2a+2b,这时候商1看看结果是否正确,即2a+2b要减去y绝对值的补码(等价于加上-y绝对值的补码)2a+2b-b=2a+b。 + +所以如果得到了一个负的余数a,可以直接转换到2a+b这个结果,即直接左移一位余数再加上除数的补码就可以得到结果。 + +这就是加减交通法或不恢复余数法。 + +从而恢复余数法就是当余数为负时商0,并+|除数|,再左移,再-|除数|,而加减交替法是当余数为负时商0,并左移,再+[除数|,若余数为正时商1,并左移,再-|除数|。 + +值得注意的是,若在最后一步余数为负,需要商0,并加上除数的补码得到正确余数。 + +注意:在定点小数运算时,商只能是小数而不能是整数,所以被除数一定要小于除数,机器判断标准是看第一步计算的商,若第一步计算的商是1则代表结果大于1,机器就会报错。 + +##### 补码加减交替法 + ++ 符号位参与运算。 ++ 被除数/余数、除数采用双符号位。 ++ 被除数和除数同号,则被除数减去除数,异号则被除数加上除数。 ++ 余数和除数同号,商1,余数左移一位减去除数; ++ 余数和除数异号,商0,余数左移一位加上除数。 ++ 重复n次。 ++ 最后一次计算时末位商横置为1,处理简单,而且精度误差也不会超过$2^{-n}$。 + +除法类型|符号位参与运算|加减次数|移位方向|移位次数次数|上商和加减原则|说明 +:------:|:------------:|:------:|:------:|:----------:|:-----------:|:---: +原码加减交替法|否|N+1或N+2|左|N|余数的正负|若最终余数为负,需恢复余数 +补码加减交替法|是|N+1|左|N|余数和除数是否同号|商末位恒置1 + +#### 强制类型转换 + ++ 无符号数与有符号数:不改变数据内容,只改变解释方式。 ++ 长整数转短整数:高位截断,保留低位。 ++ 短整数转长整数:符号扩展。 + +#### 数据存储与排列 + ++ 数据最左边的高位就是最高有效字节MSB。 ++ 数据最右边的低位就是最低有效字节LSB。 ++ 大端模式:将MSB存到最低地址,LSB存在最高地址。便于人类阅读。 ++ 小端模式:将MSB存到最高地址,LSB存在最低地址。便于机器读取。 ++ 边界对齐: + + 现代计算机通常是按字节编址即每个字节对应一个地址通常。也支持按字、按半字、按字节寻址。 + + 假设存储字长为32位,则1个字=32bit,半字=16bit。每次访存只能读/写1个字。 + + 字地址转换为字节地址,只用逻辑左移两位就可以了,即乘以4,因为字长为32,而字节长8。 + + 使用边界对齐方式会让每个数据都能一次性读完而不用跨行读取,多余的空间用0填充。 + ## 浮点数 -指小数点的位置不固定,使用科学计数法,如9.694E2。 +指小数点的位置不固定,如使用科学计数法,如9.694E2。 + +### 浮点数表示 + +#### 阶码与尾数 + ++ 定点数能表示的数字范围有限,但我们不能无限制地增加数据的长度。 ++ 类似科学计数法,分为阶码和尾数两个部分,阶码反映数值大小、表示范围、小数点实际位置,尾数反映精度。 ++ 对于二进制的浮点数,阶码是常用补码或移码表示的定点整数,而尾数是常用原码或补码表示的定点小数。 ++ 若阶码的真值为$E$,尾数的真值为$M$,则浮点数的真值为$N=r^E\times M$,其中r为阶码的底,即基数,一般为2。 + +**例题** 若阶码和尾数都使用补码表示,求对应真值:a=0,01;1.1001。 + +a的阶码为0,01,是正数,所以补码与原码一样,从数值来看就是+1。而尾数1.1001代表负数,补码为反码加1,所以真值为1,0110+1=1,0111,即=-(0.25+0.125+0.0625)。所以a的真值就是2×(-0.0111)=-0.111=-0.875(相当于乘2左移一位)。 + +#### 尾数规格化 + ++ 左规:出现下溢需要左规,即若尾数的高位是无效值(即为0)则会丧失精度,所以我们需要尽可能将尾数多保存一些1,从而让最高位为1。所以需要让数值左移,让小数点右移,尾数算术左移n位,阶码减n,直到尾数最高位是有效值。 ++ 右规:出现上溢需要右规,规范要求小数点要在第一个非0的数据右边,如果小数点前有超过1个有效位,则需要将数值右移,小数点左移,尾数算术右移n位,阶码加n,直到小数点在尾数最高位的右边。 + +**例题** 若a=010;00.1100,b=010;00.1000,求a+b的值。 + +已知分号前面的是阶码,后面是尾数,所以a和b都是2的010=2次幂。 + +由尾数的00代表a和b都是双符号位表示且都是正数。 + +所以a=2×2×00.1100,b=2×2×00.1000,则a+b=2×2×00.1100+2×2×00.1000=2×2×(00.1100+00.1000)=2×2×01.0100。 + +因为使用双符号位表示时,00代表正号,11表示负号,01时,称为上溢,为10时,称为下溢,此时结果为01,表示出现了上溢,这时候就需要右规。 + +阶码加一,变成2的三次方,尾数右移一位=2×2×2×00.1010。最后结果就是011;01010。 + +规格化浮点数的特点: + +1. 用原码表示的尾数进行规格化,最高位数值一定为1: + + 正数为0.1××...×的形式,其最大值表示为0.11...1;最小值表示为0.10...0。 + + 尾数的表示范围为$\dfrac{1}{2}\leqslant M\leqslant(1-2^{-n})$。 + + 负数为1.1××...×的形式,其最大值表示为1.10...0;最小值表示为1.11...1。 + + 尾数的表示范围为$-(1-2^{-n})\leqslant M\leqslant\dfrac{1}{2}$。 +2. 用补码表示的尾数进行规格化,符号位与最高位数值一定相反: + + 正数为0.1××...×的形式,其最大值表示为0.11...1;最小值表示为0.10...0。 + + 尾数的表示范围为$\dfrac{1}{2}\leqslant M\leqslant(1-2^{-n})$。 + + 负数为1.0××...×的形式,其最大值表示为1.01...1;最小值表示为1.00..0。(负数的补码1.0xx...x取反后就是1.1xx...x) + + 尾数的表示范围为$-1\leqslant M\leqslant-(\dfrac{1}{2}+2^{-n})$。(补码中强制规定1.00...0就代表-1) + +### IEEE 754标准 + +### 浮点数运算 ## 算术逻辑单元