12数据的表示和运算
2.1 进位计数制
古老的基数方式通过相同符号数量进行计数,个数即为符号的数量
古罗马后来优化出了罗马数字I、V、X、L、C、D、M分别对应阿拉伯数字1、5、10、50、100、500、1000
古代基于"加法"思想的计数方法不利于编写和阅读,进行优化提出了基于"乘法"思想的计数方式,进位计数制
结合古老的计数方式,符号反映权重,而基于"乘法"思想,符号所在的位置也反映权重,例如十进制,每位使用0-9的符号,逢十进一
r进制计数法,一个r进制数转换为十进制数
\(K_nK_{n-1}...K_2K_1K_0.K_{-1}K_{-2}...K_{-n}\)
= \(K_n\) x \(r^n\) + \(K_{n-1}\) x \(r^{n-1}\) + ... + \(K_1\) x \(r^1\) + \(K_0\) x \(r^0\) + \(K_{-1}\) x \(r^{-1}\) + \(K_{-n}\) x \(r^{-n}\)
其中,\(r\)表示基数,每个数码位所用到的不同符号的个数,r 进制的基数为r
\(r^i\)表示位权,指在该位置上符号的权重
二进制是最适合机器使用的进制
- 可使用两个稳定状态的物理器件表示
- 0,1 正好对应逻辑值假、真。方便实现逻辑运算
- 可很方便地使用逻辑门电路实现算术运算
八进制、十六进制可以通过二进制方便的转换,为方便阅读可使用八进制、十六进制来表示计算机中的二进制数据
| \(2^{12}\) | \(2^{11}\) | \(2^{10}\) | \(2^9\) | \(2^8\) | \(2^7\) | \(2^6\) | \(2^5\) | \(2^4\) | \(2^3\) | \(2^2\) | \(2^1\) | \(2^0\) | \(2^{-1}\) | \(2^{-2}\) | \(2^{-3}\) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 4096 | 2048 | 1024 | 512 | 256 | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 | 0.5 | 0.25 | 0.125 |
2.1.1 进制的书写方式
- 二进制 1010B=(1010)\(_2\)
- 八进制 (113764)\(_8\)
- 十进制 不进行标注,默认为十进制,或书写为1002D
- 十六进制 13BFH=0x13BF
2.1.2 十进制转换其他进制
整数部分:除基取余法,先得到的余数为整数的地位
小数部分:乘基取整法,先得到的整数位小数的高位
有些的十进制小数无法用其他进制精确表示,如:0.3无法用二进制精确表示
2.1.3 其他进制转换
二进制—>八进制
- 3位一组,毎组转换成对应的八进制符号
二进制—>十六进制
- 4位一组,毎组转换成对应的十六进制符号
八进制—>二进制
- 每位八进制对应的3位二进制
十六进制—>二进制
- 每位十六进制对应的4位二进制
由于数是有位数的,如果进制转换后位数变化了,需要补位
2.2 定点数和编码表示
2.2.1 数的表示
定点数:小数点的位置固定,即常规的计数方式
浮点数:小数点的位置不固定,如科学计数法
各种进制的数均可以用定点数、浮点数表示
无符号数:整个机器字长的全部二进制位均为数值位,没有符号位,相当于数的绝对值
- 通常只有无符号整数,而没有无符号小数
- n位的无符号数表示范围为:0 ~ \(2^n\)-1
带符号数:最高位二进制位表示符号位,其他位表示数值位,也称作尾数
浮点数一定是带符号数
2.2.2 编码的表示
真值:符合人类习惯的数字
机器数:数字实际存到机器里的形式,正负号需要被"数字化"
原码:用尾数表示真值的绝对值,符号位"0/1"对应"正/负"
- 对于带符号数整数,若机器字长n+1位,原码整数的表示范围:−(\(2^n\)−1) ≤ x ≤ \(2^n\)−1
- 变量x机器数为10010011,常写作[x]\(_原\)=1,0010011B。如果没有表明机器字长,原码表示可直接[x]\(_原\)=1,10011B
- 对于真值0,区分+0和-0
- 对于浮点数,若机器字长为n+1位,则尾数占n位
- 若机器字长n+1位,原码浮点数的表示范围:−(1−\(2^{−n}\)) ≤ x ≤ 1−\(2^{−n}\)
- 对于真值0,区分+0和-0
反码:若符号位为0,则反码与原码相同;若符号位为1,则数值位全部取反
- "反码"只是"原码"转变为"补码"的一个中间状态,实际中并没什么应用场景
- 反码的整数、浮点数的表示范围和原码相同,且对于真值0区分+0和-0
补码:正数的补码 = 原码;负数的补码= 反码末位+1,由于+1的原因需要考虑进位
- 将负数补码转回原码的方法相同:尾数取反,末位+1
- 补码的真值0只有一种表示形式,[+0]\(_补\) = [-0]\(_补\)= 00000000B
- 若机器字长n+1位,补码整数的表示范围:−\(2^n\) ≤ x ≤ \(2^n\)−1,比原码多一个−\(2^n\)
- 若机器字长n+1位,补码浮点数的表示范围:−1 ≤ x ≤ 1-\(2^{-n}\),比原码多一个−1
移码:补码的基础上将符号位取反
- 移码只能用于表示整数,移码全0真值最小,移码全1真值最大
- 若机器字长n+1位,移码整数的表示范围:−\(2^n\) ≤ x ≤ \(2^n\)−1,与补码相同
源码、反码、补码相互转化
原码、反码、补码三种方式均可表示定点整数和定点小数,还可用移码表示定点整数
若真值为x,则用[x]\(_原\)、[x]\(_反\)、[x]\(_补\)、[x]\(_移\)分别表示真值所对应的原码、反码、补码、移码
x\(_{真值}\) -> [x]\(_原\)
- 数值位不变,增加符号位,正数最高位加0;负数最高位加1
[x]\(_原\) <-> [x]\(_反\)
- 符号位不变,若符号位为0,数值位不变;若符号位为1,数值位取反
[x]\(_原\) <-> [x]\(_补\)
- 符号位不变,若符号位为0,数值位不变;若符号位为1,数值位取反后+1
[-x]\(_补\) <-> [x]\(_补\)
- 符号位不变,数值位取反后+1
[x]\(_补\) <-> [x]\(_移\)
取反加一技巧:最右边的1及其右边同原码,最右边的1的左边同反码
2.2.3 各种编码的应用
直接使用原码进行加、减法运算,不论是无符号数还是带符号数,均会存在进位、借位的情况
- 进位、借位需要专门的硬件电路进行实现。原码加法需要使用加法器完成,原码减法需要用减法器完成
- 减法器电路实现难度较大,但如果使用加法去替代减法,则硬件电路只需要实现加法功能即可
加法替代减法
- 假设要计算10点3个小时前是几点,由于时间是是二进制的,可通过(10+9) mod 12=7,实现减法的过程
- 带余除法,设x,m∈Z,m>0,则存在唯一决定的整数q和r,使得x = q * m +r,0 ≤ r < m。其中r位余数
- k的模运算将所有整数分为k类,余数相同的数位同一类都是等价的
- 上述模运算中,-3和9是等价的,即-3 ≡ 9 mod 12 或 -3 mod 12 = 9。除此之外,21,33,-15均与-3,9等价
- 两个等价的数绝对值之和等于模,如-3和9,则称两个数互为补数
- 对于计算机的二进制,假设机器字长位8bit,则每次加法的运算结果都进行mod \(2^8\),为了实现减法运算,需要增加该真值绝对值的补数
- 模-真值a的绝对值=a的补数,而这个补数正是该真值的补码,从而将减法运算转换为加法,ALU中无需集成减法器,节省硬件成本
- 执行加/减法运算时,机器数中的符号位也是参与运算的
移码表示的整数均是无符号数,因此很方便对比大小
2.3 零扩展与符号扩展
计算机的机器字长决定了该计算机中的通用寄存器、逻辑算术单元ALU的最大可以存储多少位bit。对于相同指令集体系结构的计算机,存储在主存中用于计算机的不同变量类型所占机器数位数和机器字长必然是不同的,ALU计算或存入到通用寄存器中就必然不可避免出现需要将数据进行扩展的情况
- 对于无符号整数,短数据扩展为长数据,直接用0扩展高位
- 对于带符号整数(补码),短数据扩展为长数据,直接用"符号位"扩展高位
2.3.1 C语言中的强制类型转换
C语言中的定点整数主要使用int、long、short等类型变量存储,并且均是使用补码进行存储。C语言中定点证书类型默认是带符号数,如果需要使用无符号数需要在类型名前增加unsigned关键字
// 真值61215
// x:1110 1111 0001 1111
// y:1110 1111 0001 1111
void main(){
//有符号数与无符号数相互强制转换:不改变机器数,只改变解释方式
short x=-4321; //short型占用2个字节
unsigned short y=(unsigned short)x;
//长整数强制转换为短整数:高位截断,保留低位
int a=165537, b=-34991; //int型占用4个字节
short c=(short)a, d=(short)b; //short型占用2个字节
//a:0x000286a1,真值为165537
//c:0x86a1 高位截断,真值变为-31071
//b:0xffff7751,真值为-34991
//d:0x7751 连着符号位一同高位截断,真值变为30545
//短整数强制转换为长整数:符号扩展,由于存储的都是补码,真值并不会发生变化
short x=-4321;
int m=x;
unsigned short n=(unsigned short)x;
unsigned int p=n;
//x:1110 1111 0001 1111,0xef1f,真值-4321
//m:1111 1111 1111 1111 1110 1111 0001 1111,0xffffef1f,真值-4321
//n:1110 1111 0001 1111,0xef1f,真值61215
//p:0000 0000 0000 0000 1110 1111 0001 1111,0x0000ef1f,真值61215
}
2.4 数字编码以及算数的硬件实现
2.4.1 逻辑门电路
算数运算:人们常见的数字运算方式,如加减乘除的基本算术运算,以及复合算术运算幂次方
计算机存储的数据均为二进制,二进制的逻辑运算通过逻辑门电路进行,逻辑门电路包括基本逻辑运算与、或、非,以及符合逻辑运算与非、或非、异或、同或
逻辑运算:对逻辑值 真/假或二进制1/0 进行运算,如与、或、非、异或
不论是算数运算还是逻辑运算,都必须有输入、输出
基本逻辑运算:与,AND
- 表达式:Y= A · B 或 Y= AB,输入逻辑值只能为2个
- 真值表:有0则输出0,全1输出1
逻辑门电路的图形符号可采用国标画法GB/T 4728.02-1996,也可采用国际常用画法表示
- 与门图形符号中,左侧输入端为竖直线,右侧输出形式不固定
基本逻辑运算:或,OR
- 表达式:Y= A + B,输入逻辑值只能为2个
- 真值表:有1则输出1,全0输出0
- 或门图形符号中,左侧输入端为向内凹的弧线,右侧输出形式不固定
基本逻辑运算:非,NOT
- 表达式:Y= \(\overline{\text{A}}\),输入信号值只能为1个
- 真值表:输入1则输出0,输入0则输出1
- 非门图形符号中,左侧输入或输出端处有小圆圈
复合逻辑运算:与非,NOT-AND,NAND
- 表达式:Y= \(\overline{\text{A}·\text{B}}\) 或Y= \(\overline{\text{AB}}\),输入逻辑值只能为2个
- 真值表:有0则输出1,全1则输出0
- 与非门图形符号,可以用与门、非门串联的方式进行表示,也可以在与门符号基础上在右侧输出端处增加小圆圈进行表示
复合逻辑运算:或非,NOT-OR,NOR
- 表达式:Y= \(\overline{\text{A}+\text{B}}\),输入逻辑值只能为2个
- 真值表:有1则输出0,全0则输出1
- 或非门图形符号,可以用或门、非门串联的方式进行表示,也可以在或门符号基础上在右侧输出端处增加小圆圈进行表示
复合逻辑运算:异或,exclusive OR,XOR
- 表达式:Y= A⊕B或Y= \(\overline{\text{A}}\text{B}\)+\(\text{A}\overline{\text{B}}\),输入逻辑值只能为2个
- 真值表:输入逻辑值相同则输出0,输入逻辑值不同则输出1
- 异或门图形符号,可以在或门符号基础上,左侧输入端多加一个弧线
- 如果用基本逻辑运算实现,则需要两组非与门(非门和与门进行串联),两组非与门再和一个或门串接
- 为了方便表示,一般不将所有基本逻辑运算符号表示出来
"封装"思想:屏蔽电路部件的内部实现细节,仅对外暴露出输入/输出引脚。使用者仅关心该部件的整体功能
复合逻辑运算:同或/异或非门,exclusive NOT-OR,XNOR
- 表达式:Y= A⊙B或Y=\(\overline{\text{A⊕B}}\),输入逻辑值只能为2个
- 真值表:输入逻辑值相同则输出1,输入逻辑值不同则输出0
- 同或门图形符号,为了方便表示,直接在异或门电路后串接一个非门,或也可以再异或门基础上在右侧输出端增加小圆圈
逻辑门电路应用
n bit进行异或,若有奇数个1,则异或结果为1;若有偶数个1,则异或结果为0
- 该方法可用于实现奇偶校验、二进制加法
扩展门电路
基础门电路均为双目/单目逻辑门,基础门电路可扩展为多输入的门电路,如多输入或门(Y= A + B + C)、多输入与门(Y= ABC)、多输入或非门(Y= \(\overline{\text{A}+\text{B}+\text{C}}\))、多输入与非门(Y= \(\overline{\text{ABC}}\))
逻辑运算优先级与常见公式
三种基本逻辑运算优先级:非 > 与 > 或
- 与可以类比成乘法,或可以类比成加法
- 逻辑表达式中,括号和算术运算一样,可以提高运算优先级
- 非运算符下为包含多个逻辑值的表达式,先计算表达式的逻辑结果在进行非运算,即非运算符下"隐含一个括号"
逻辑运算满足以下运算规律
- 分配律:A(C+D)=AC+AD
- 与运算的结合律:(AB)C=A(BC)
- 或运算的结合律:A+B+C=A+(B+C)
- 反演律:
- \(\overline{\text{A}+\text{B}}\)=\(\overline{\text{A}}\ ·\ \overline{\text{B}}\)
- \(\overline{\text{A}·\text{B}}\)=\(\overline{\text{A}}+\overline{\text{B}}\)
用电路实现符合逻辑运算AC+AD时
- 从表达式角度,电路实现可以设计两个与门,两个与门后再串接一个或门,AC、AD分别与,结果输出到或门输出最终结果。即需要两个与门以及一个或门
- 如果通过分配律变为A(C+D),则只需要一个或门以及一个与门,CD进行或的结果在与A进行与门输出最终结果
本质上逻辑表达式是对电路的数字化描述,简化逻辑表达式就是简化电路设计,可以减少制造成本
逻辑门电路制程
使用门电路设计电路,可实现二进制运算。而门电路由晶体管实现,晶体管越小,功耗越低、单位面积内晶体管数量更多,即可实现更复杂的硬件功能
某芯片采用10nm制程——意味着该芯片内部的晶体管栅极宽度为10nm。头发丝直径约为0.1mm = 100,000nm
晶体管关键制造设备:光刻机
2.4.2 多路选择器与三态门
多路选择器,multiplexer,MUX
- 作用:电路的"守门员"。在多个输入数据中,只允许其中一个数据通过MUX
- 图形表示:MUX常用梯形表示,有多个输入、一个输出、一个控制型号。梯形更长的一端是输入端,更短的一边为输出端
在电路图中,控制信号常用英文缩写"XXXop"表示,图形常用虚线箭头,直接指向MUX
- 控制信号op会传入一个数据来告知MUX选择哪个数据。若有k个输入,则控制信号的位数m ≥ \(\lceil log_2k \rceil\) bit
- 假设某多路选择器有4个输入,则控制信号op有2位,并将四个输入分别标号00B、01B、10B、11B。若op=01B,则表示MUX目前允许01B号输入通过MUX
有些MUX可能会预留一个控制信号,用于拦截所有的输入,那么控制信号的位数m ≥ \(\lceil log_2\)(k+1)\(\rceil\) bit
三态门
- 作用:类似于MUX,电路的"守门员"。根据控制信号决定是否让输入的数据通过
- 图形:一个小三角。有一个输入、一个输出、一个控制信号
- 三态门的控制信号通常只需要1bit。op=1表示允许数据通过;op=0表示不允许数据通过,同时输出端处于高阻态状态
高阻态不同于高电平、低电平状态,他的电路相当于断路
三态门图形和非门很像,三态门可以在输出端处增加小圆圈,在三态门基础上实现非运算。在这种情况下,三态非门和非门的唯一区别就是有无控制信号
2.4.3 加法器
加法器是实现计算机加法运算的元件,通过设计一位加法器并进行组合,可实现nbit的加法
不论是什么类型的加法器,实际使用时不需要考虑具体的物理结构,仅需关心加法器的逻辑功能
一位加法器
一位全加器,full adder,FA
- 假设\(A_i\)为被加数的本位,\(B_i\)为加数的本位,\(C_{i-1}\)为来自低位 i-1 的进位,\(C_i\)为向高位 i+1 的进位,\(S_i\)为本位和
- 当\(A_i,B_i,C_{i-1}\)的输入中有奇数个1时,本位和\(S_i\)输出1,即\(S_i\) = \(A_i\) ⊕ \(B_i\) ⊕ \(C_{i-1}\)
- 当\(A_i,B_i,C_{i-1}\)的输入中至少两个输出1时,进位\(C_i\)输出1,即\(C_i\) = \(A_iB_i\) + (\(A_i\) ⊕ \(B_i\))\(C_{i-1}\) = \(A_iB_i\) + (\(A_i\) + \(B_i\))\(C_{i-1}\)
- FA有三个输入,两个输出
串行进位加法器
串行进位加法器,也称为串行进位的并行加法器
-
将n个一位加法器串接,构成n位加法器时,输入\(A_i\)、\(B_i\)分别构成被加数、加数的各个位,且只需要输入最低位\(C_0\)一个进位,产生结果\(S_i\)以及最高位进位\(C_n\)
-
由于FA之间的进位信息时串行产生的,计算速度取决于进位产生和传递的速度,位数越多,运算速度越慢
电信号到达稳态需要一定时间,因此进位产生速度会有延迟
串行进位又称为行波进位,每一级进位直接依赖于前一级的进位,即进位信号是逐级形成
并行进位加法器
并行进位加法器,也称并行进位的并行加法器
- 所有进位信息都是同时产生的,几乎没有延迟,运算速度比"串行进位的并行加法器"更快
- 各级进位信号同时形成,又称先行进位、同时进位。通过电路,每个加法器将两个输入A、B,进行与计算\(G_i\) = \(A_iB_i\),以及异或计算\(P_i\) = \(A_i\) ⊕ \(B_i\),并发计算每个位的进位\(C_i\),提高效率
每个FA的进位\(C_i\)表面上每个\(C_i\)依赖于前一个\(C_{i-1}\)结果计算,进步一步展开
\(C_i\) = \(A_iB_i\) + (\(A_i\) ⊕ \(B_i\))\(C_{i-1}\)
=\(A_iB_i\) + (\(A_i\) ⊕ \(B_i\))[\(A_{i-1}B_{i-1}\) + (\(A_{i-1}\) ⊕ \(B_{i-1}\))\(C_{i-2}\)]
...
- 因此,第i位向更高位的进位\(C_i\)可根据被加数、加数的第1~i位,以及结合\(C_0\)即可确定
- 记\(G_i\) = \(A_iB_i\),\(P_i\) = \(A_i\) ⊕ \(B_i\),则有\(C_i\) = \(G_i\) + \(P_iC_{i-1}\)
- \(C_1\) = \(G_1\) + \(P_1C_0\)
\(C_2\) = \(G_2\) + \(P_2C_1\) = \(G_2\) + \(P_2G_1\) + \(P_2P_1C_0\)
\(C_3\) = \(G_3\) + \(P_2C_2\) = \(G_3\) + \(P_3G_2\) + \(P_2P_1G_1\) + \(P_3P_2P_1C_0\)
... - 由于高位的\(C_i\)所参与运算的\(A_i,B_i\)较多,全部使用普通一位加法器表示电路会过于复杂。因此可以设计由多个FA组成的新加法器进行表示。如4位CLA加法器,由4个FA和一些新的线路、运算逻辑组成
带标志位的加法器
1.上述实现方式,如果只考虑进位\(C_i\)和结果\(S_i\)作为输出,加法器计算结果是否发生溢出无法判断
2.计算机在判断条件表达式if(A==B)时,可转换为判断表达式A+(-B)==0的加法结果是否为0,从而判断A是否等于B
- 同理在判断
if(A>B)时,也可改为A+(-B)>0的加法结果是否大于0 - 因此,加法器产生的结果也可能需要区分正负
结合两个方面的考虑,在并行加法器的基础上,增加标志位的输出ZF、OF、SF、CF
- 溢出标志OF,Overflow Flag,用于判断带符号数加减运算是否溢出。OF=1 溢出;OF=0 未溢出
- OF = \(C_n\) ⊕ \(C_{n-1}\),即最高位的进位 ⊕ 次高位的进位。反映带符号数加减运算是否溢出
- 符号标志SF,Sign Flag,用于判断带符号数加减运算结果的正负性。SF=1 结果为负;SF=0 结果为正
- SF = \(S_n\),也就是取运算结果的最高位/符号位。由于计算机存储数据都是存放真值的补码,因此可直接反映带符号数加减运算的正负性
- 零标志ZF,Zero Flag,用于判断加减运算结果是否为0。ZF=1 表示结果为0;ZF=0 表示结果不为0
- ZF=\(Sn\) + ⋯ + \(S_2\) + \(S_1\),仅当运算结果所有bit全0时,ZF才为1,此时表示运算结果为0
- 进位/借位标志CF,Carry Flag,用于判断无符号数加减运算是否溢出。CF=1 溢出;CF=0 未溢出
- CF = \(C_{out}\) ⊕ \(C_{in}\) = \(C_n\) ⊕ \(C_0\),反映无符号数加减运算是否溢出
2.4.4 算数逻辑计算单元ALU
算数逻辑单元ALU,Arithmetic and Logic Unit
- ALU是一种组合逻辑电路,实现了算数运算(如加/减/乘/除)、逻辑运算(如与/或/非)以及其他拓展功能(如求补码、直送),是CPU运算器的核心
- 加减乘除运算都是基于加法实现的,加法器是ALU的核心
- ALU包括两个输入,一个输出,以及一个m bit的控制信号输入(由控制器产生)。如果ALu支持k种功能,则控制信号位数m ≥ \(\lceil log_2k \rceil\)
- ALU内部实现了加法、乘法、与运算、位移运算等功能电路,功能电路全部串接在多路选择器MUX上,ALU收到的控制信号直接作用在这个MUX上
- 当输入A、B时,会将A、B同时传入所有功能电路中,接受来自控制器发出的控制信号,决定此时输出哪个功能电路的结果
ALU的运算数、运算结果位数与计算机机器字长相同
ZF/OF/SF/CF 标志位,用于表示本次运算结果的特征
ZF表示运算结果是否为零、OF表示有符号数运算结果是否溢出、SF表示有符号数运算结果的正负性、CF表示无符号数运算结果是否溢出
- 这些标志信息通常会被送入PSW 程序状态字寄存器
有的计算机系统把PSW寄存器称为标志寄存器FR,Flag Register
Cin 是进位输入信号,Cout 是进位输出信号
2.4.5 补码加减运算电路
由于计算机中存放的均是补码,而且减法运算通过加法去实现,显然n bit的加法器无法实现
补码加减运算电路
- 被加数输入端A不需要修改;而在加数输入端,逻辑输入B和一个非门一同接在多路选择MUX上,多路选择器输出结果作为加法的输入
- 多路选择MUX上接受Sub 加/减法控制信号,当输入信号为0时表示加法,输入信号为1时表示减法
- 同时Sub控制信号的值会作为低位进位Cin输入给加法器。实现取反加一的操作
- 同带标志位的加法器,将标志位引入电路中,输出给程序状态字寄存器PSW
补码加减运算电路也可用于计算无符号数加减运算
2.5 定点数编码的运算
2.5.1 定点数移位运算
算数移位:通过改变各个数码位和小数点的相对位置,从而改变各数码位的位权
- 算数左移:低位补0,高位舍弃,若舍弃的位不等于新的符号位则发生溢出
- 算数右移:高位补符号位,低位舍弃,若低位舍弃1则发生数据丢失
- 算数移位的应用,如要计算-20D x 7D
- 7D=111B=\(2^0\) + \(2^1\) + \(2^2\)
- -20D x 7D = -20D x (\(2^0\) + \(2^1\) + \(2^2\)) = -20D + -40D + -80D
- 将乘法过程拆解为不左移,左移1位,左移2位三部分,求和
逻辑移位:将操作数作为无符号数进行算数移位
- 逻辑左移:低位补0,高位舍弃,若舍弃的位为1则发生溢出
- 逻辑右移:高位补0,低位舍弃,若低位舍弃1则发生数据丢失
- 逻辑移位的应用,可将一个固定位数的编码,拆分成几个部分分别存储信息
- 如RGB高8位存放Red值,中8位存放Green值,低8位存放Blue值
在计算机中其实不区分算数移位和逻辑移位,只由数据的类型决定
循环移位:当进行移位时,舍弃的位直接作为需要补充的位
- 带进位位的循环左移:连带着进位位一同位移,舍弃的位直接作为需要补充的位
加法的运算结果保留进位符号,如果发生溢出修改进位位标记
2.5.2 定点数加减运算
有符号数加减运算
带符号数(补码)的加法:从最低位开始,按位相加(符号位参与运算),并往更高位进位
同时,计算机中减法一般都通过 [A]\(_补\) - [B]\(_补\) = [A]\(_补\) + [-B]\(_补\) 来实现
- 加法器直接对原码进行加法运算,当加数和被加数同号可能会发生溢出
- 对于补码而言,符号位也一同参与运算,溢出情况需要进行判断
- 当一个数小于他的数值最小表示数,则表示下溢;当一个数大于他的数值最大表示数,则表示上溢
正数+正数会发生上溢出,即正+正=负;负数+负数会发生下溢出,即负+负=正
溢出判断
- 一位符号位判断溢出:设A的符号为\(A_S\),B的符号为\(B_S\),运算结果的符号为\(S_S\),则溢出逻辑表达式为 V = \(A_SB_S\overline{S_S}\) +\(\overline{A_S} \ \overline{B_S}S_S\)。若V=0,表示无溢出;若V=1,表示有溢出
\(A_S\)为1且\(B_S\)为1且\(S_S\)为0,\(A_S\)为0且\(B_S\)为0且\(S_S\)为1
- 采用一位符号位,根据数据位进位情况判断。记溢出符号位的进位\(C_S\),最高数值位的进位\(C_1\),溢出逻辑判断表达式为V = \(C_S\) ⊕ \(C_1\)。若V=0,表示无溢出;V=1,表示有溢出
\(C_S\)和\(C_1\)不同时有溢出
- 采用双符号位正数符号为00,负数符号为11。记两个符号位为\(S_{S1},S_{S2}\),则V = \(S_{S1}\) ⊕ \(S_{S2}\)。若V=0,表示无溢出;若V=1,表示有溢出
双符号位补码又称模4补码,单符号位补码又称模2补码
实际存储时只存储1个符号位,运算时会复制一个符号位,使得两个符号位一起参与运算
无符号数加减运算
无符号整数的加法:从最低位开始,按位相加,并往更高位进位
无符号整数的减法:同带符号数的减法,被减数不变,减数全部位按位取反末位+1,将减法变加法,再按位相加并向更高位进位
溢出判断
- 手算判断溢出的方法:n bit 无符号整数表示范围0~\(2^n\)-1,超出此范围则溢出
- 计算机判断溢出的方法
- 加法的溢出判断:最高位产生的进位=1时,发生溢出,否则未溢出
- 减法的溢出判断:减法变加法,最高位产生的进位=0时,发生溢出,否则未溢出
2.5.3 定点数乘法运算
手算乘法采用的是乘数的每一位与被乘数相乘,相乘结果乘上该位的权值进行相加得到最后的乘积
乘积结果分为符号位和数值位
- 符号位单独处理,符号位 = x ⊕ y
- 数值位取绝对值进行乘法计算,并采用"先加法再移位,重复n次"
- 在运算器中,乘法运算,累加寄存器ACC存放乘积高位,乘商寄存器MQ存放乘数、乘积低位,通用寄存器X存放被乘数
原码的一位乘法

设机器字长为n+1=5位(含1位符号位),[x]\(_原\)= 1.1101B,[y]\(_原\)= 0.1011B,采用原码一位乘法求x·y
- 符号位=Xs ⊕ Ys,取X、Y数值的绝对值作为被乘数X=0.1101和乘数MQ=0.1011
- 乘数从最右低位开始依次运算,直到当前位为乘数MQ的符号位,即。假定运算过程的中间结果都存放在ACC中,ACC初值为00000,ACC的最高位为符号位
- 每次运算过程:
- 若当前乘数MQ的位=1,则(ACC) + (X) -> ACC
- 若当前乘数MQ的位=0,则(ACC) + 0 -> ACC
- 乘数MQ进行逻辑右移,低位舍弃,ACC也逻辑右移,高位补0,最低位移到MQ的最高位上
- ACC上的位和右移到MQ上的位合并的数,称为部分积。部分积共5+4位,其中ACC最高位为符号位0,乘积结果小数点在ACC符号位,得运算结果为1.10001111B,即x · y = -0.10001111B
备注:
- 乘数的符号位不参与运算,可以省略。原码一位乘可以只用单符号
- 答题时最终结果最好写为原码机器
上述运算过程中,运算次数=有效数次数
如果为整数的原码乘法运算,步骤同上,乘积结果小数点在部分积末尾
补码的一位乘法
补码的一位乘法,也叫布斯乘法
- 补码一位乘法和原码一位乘法类似,但最后再多来一次加法。每轮加法可能 +0,+[x]\(_补\),+[-x]\(_补\),由MQ中的最低位以及辅助位决定
- 每次移位时补码的算术右移,符号位也参与运算

假设机器字长为5位=1+n位,x=-0.1101,y=+0.1011,[X]\(_补\)=11.0011,[-X]\(_补\)=00.1101B,[y]\(_补\)=00.1011B
- 同原码一位乘法,使用ACC和MQ存储部分积,但MQ在5位基础上在低位多加1位辅助位(MQ共n+2位),该辅助位初始为0,每次右移会使MQ的最低位顶替原本的辅助位。为了保证对齐,X和ACC寄存器也统一采用n+2位,置于最高位,采用双符号位补码运算
- 每次运算过程:
- 若辅助位-当前位(MQ最低位)=1时,(ACC) + [X]\(_补\) -> ACC
- 若辅助位-当前位=0时,(ACC) + 0 -> ACC
- 若辅助位-当前位=-1时,(ACC) + [-X]\(_补\) -> ACC
- 计算完后,乘数进行算数右移,高位补符号位
- 小数点同原码一位乘法,运算结果为11.011
备注:
- 部分积、被乘数采用双符号位补码
- 乘数采用单符号位补码,并在末位添个0
2.5.4 除法运算
原码恢复余数法

假设机器字长位5位=1+n位,x=0.1011B,y=0.1101B
- 符号位 = \(X_s\) ⊕ \(Y_s\),[|x|]\(_原\)=0.1011B,[|y|]\(_原\)=0.1101B,[|y|]\(_补\) =0.1101 ,[-|y|]\(_补\)=1.0011
- ACC存放被除数以及之后的余数,MQ存放商,X存放除数,依次计算商MQ的位,直至填满。MQ初值为0
- 每次运算过程:
- 计算商的当前位,计算机先假定该位为1,将ACC-除数得到的值作为余数,(ACC) + [-|y|]\(_补\) -> ACC
- 若此时ACC符号位为正,则直接下一步
- 若此时ACC符号位为负,说明商的当前位应该为0,ACC恢复原余数,(ACC) + [|y|]\(_补\) -> ACC,并加回被除数(ACC) + (X) -> ACC。ACC进行逻辑左移,高位舍弃,MQ也进行逻辑左移,低位补0,最高位移到ACC最低位
- 余数ACC的小数点在左数第二位,商MQ小数点在左数第二位,得运算结果为商0.1101,余0.0111 x \(2^{-n}\),余数与商符号同号
原码加减交替法/不恢复余数法
加减交替法是对恢复余数法的优化:
- 当余数ACC为负时,商0,余数ACC左移1位,加上除数绝对值,(ACC) + [|y|]\(_补\) -> ACC
- 当余数ACC为正,商1,余数ACC左移1位,减去除数绝对值,(ACC) + [-|y|]\(_补\) -> ACC
补码加减交替法

假设机器字长为5位=1+n位,x=+0.1000B,y=-0.1011B,采用双符号位,[x]\(_补\)=00.1000,[y]\(_补\)=11.0101,[-y]\(_补\)=00.1011
- 第一次运算,比较被除数和除数的符号:
- 同号则被除数减去除数,[x]\(_补\) + [-y]\(_补\) -> ACC
- 异号则被除数加除数,[x]\(_补\) + [y]\(_补\) -> ACC
- 第一次运算不计算商,只用于确定余数初值
- 后续每次运算过程,比较余数和除数符号:
- 若同号,则商1,余数左移1位,再减去除数,(ACC) + [-y]\(_补\) -> ACC
- 若异号则商0,余数左移1位,再加上除数,(ACC) + [y]\(_补\) -> ACC
- 在计算商的最后一位时有可能商0,关于最后一位有两种校正方案
- 恒置1法:余数恒置1,获得近似值,精度误差不超过\(2^{-n}\)
- 校正法:若最后一位能除尽,除数Y为正不必校正;除数Y为负,商加上2^(-n)进行校正。若最后一位不能除尽,商为正不必校正;商为负,商加上\(2^{-n}\)进行校正
2.6 浮点数的表示
定点数可表示的数据范围有限,也不可能通过无限制的增加数据类型的长度来扩展数据表示范围,可通过科学计数法的方式表示更大的数,通过阶码反映数值大小,
浮点数分为阶码和尾数,真值N = \(r^E\) x M
- r表示阶码,通常为2;阶码E反映浮点数的表示范围及小数点的实际位置;尾数M的数值部分的位数n反映浮点数的精度。尾数给出一个小数,阶码指明了小数点要向前/向后移动几位
- 阶码常用补码或移码表示的定点整数,尾数常用原码或补码表示的定点小数
- 阶码最高位表示阶数的符号,尾数的最高位表示数值的符号。阶码反映数值大小,尾数反映精度
如b = 0,10;0.01001。阶码0,10对应真值+2,尾数0.01001对应真值+0.01001 = + (\(2^{-2}\)+ \(2^{-5}\)),则b的真值为\(2^2\)×(+0.01001)= +1.001
尾数最高位为无效位时,会损失精度。为了保证精度,需要进行规格化
- 规范化浮点数:规定尾数的最高数值位必须是一个有效值
- 通过对尾数算数左移、阶码减1 来规格化(左规):当浮点数运算的结果为非规格化时要进行规格化处理,将尾数算数左移一位,阶码减1
- 通过对尾数算数右移、阶码减1 来规格化(右规):当浮点数运算的结果尾数出现溢出(双符号位为01或10)时,将尾数算数右移一位,阶码加1
- 采用"双符号位",当溢出发生时,可以挽救。更高的符号位是正确的符号位
浮点数进行规范化后,有如下特点
- 规格化的原码尾数,最高数值位一定是1
- 规格化的补码尾数,符号位与最高数值位一定相反
对于非规格化浮点数,有如下特征
- 尾数前的数值位不包含1,阶码固定为-126
- 如1000 0000 0100 000 0000 0000 0000
- 阶码为0,但尾数不为0,显然他不是IEEE的规格化0,是一个接近0的负数,则其最高数值位不为1
- 阶码为-126,则该数为-(0.1)B x 2\(^{-126}\) = -2\(^{-127}\) ≈-5.87 x 10\(^{-39}\)
2.6.1 IEEE754浮点数表示法
移码:补码的基础上将符号位取反,只能用于表示整数
- 移码=真值+偏置值
- 假设机器字长为n,偏置值一般取\(2^{n-1}\),此时移码=补码符号位取反
IEEE754标准:
- 机器码分为三部分,最高位数符\(m_s\)、阶码E、尾数M,阶码用移码表示,尾数用原码表示
相比一般浮点数定义,只保留一个符号位,增加了精度,1表示负数,0表示正数
尾数部分最高位的隐含位1,即尾数部分原码真值为+1.xxxxB
- IEEE754定义了多种浮点类型,单精度浮点型float、双精度浮点型double、长浮点型long double,三种类型的数符\(m_s\)均占1位
- float共32位,阶码占8位,尾数占23位。偏置值为127,阶码真值正常范围为-126~127,因此真值N = \((-1)^{m_s}\) x 1.M x 2\(^{E-127}\)
- 最小绝对值:尾数全为0,阶码真值最小-126,对应移码机器数0000 0001,此时整体的真值为(1.0)2×2\(^{-126}\)
- 最大绝对值:尾数全为1,阶码真值最大127,对应移码机器数1111 1110,此时整体的真值为(1.111...11)2×2\(^{127}\)
- double共64位,阶码11位,尾数占52位。偏置值为1023,因此真值N = \((-1)^{m_s}\) x 1.M x \(2^{E-1023}\)
- long double共80位,阶码占15位,尾数占64位
- 阶码全1和全0保留用于特殊用途
- 阶码E全为0,尾数M不全为0时,表示非规格化小数 ±(0.xx...x)2×2-1
- 阶码E全为0,尾数M全为0时,表示真值 ±0
- 阶码E全为1,尾数M全为0时,表示无穷大 ±∞
- 阶码E全为1,尾数M不全为0时,表示非数值"NaN" (Not a Number)。如0/0、∞-∞等非法运算结果
2.6.2 浮点数加减运算
浮点数加减运算步骤:
- 对阶:小阶向大阶转换,统一阶数。在计算机内部,尾数是定点小数
- 尾数加减:位加/减,并向上进位
- 规格化:尾数最高位为无效位则左归,加/减结果整数部分位数变化则右归
- 舍入:如规定只保留特定位数的有效尾数,规定只有浮点数存在舍入现象
- 有的计算机可能会把浮点数的尾数部分单独拆出去计算(24bit->32bit),算完了经过舍入(32bit->24bit)再拼回浮点数
- "0"舍"1"入法:类似于十进制数运算中的"四舍五入"法,即在尾数右移时,被移去的最高数值位为0,则舍去;被移去的最高数值位为1,则在尾数的末位加1。这样做可能会使尾数又溢出,此时需再做一次右规
- 恒置"1"法:尾数右移时,不论丢掉的最高数值位是"1"还是"0",都使右移后的尾数末位恒置"1"。这种方法同样有使尾数变大和变小的两种可能
- 判溢出:若进行规格化和舍入后,运算后阶码仍超出范围,则表明发生溢出
已知十进制数X=−5/256、Y=+59/1024,按机器补码浮点运算规则计算X−Y,结果用二进制表示,浮点数格式如下:阶符取2位,阶码取3位,数符取2位,尾数取9位
- 转换格式:用补码表示阶码和尾数
- 5D = 101B,1/256 = \(2^{-8}\)
=> X = - 101B × \(2^{-8}\) = - 0.101B × \(2^{-5}\) = - 0.101B × \(2^{-101B}\) - 59D = 111011B,1/1024 = \(2^{-10}\)
=> Y = + 111011B × \(2^{-10}\) = + 0.111011B × \(2^{-4}\) = + 0.111011B × \(2^{-100B}\) - X:11011,11.011000000;Y:11100,00.111011000
- 5D = 101B,1/256 = \(2^{-8}\)
- 对阶:使两个数的阶码相等,小阶向大阶看齐,尾数毎右移一位,阶码加1
- 求阶差:[ΔE]\(_补\)=11011B+00100B=11111B,知ΔE=−1,X的阶小向大阶对齐
- 对阶:X:11011,11.011000000B => 11100,11.101100000B
- 尾数相减
- -Y:11100,11.000101000B,X-Y:11100,10.110001000B
- 规格化:X-Y:11100, 10.110001000B => 11101,11.011000100B
- 舍入:无需舍入
- 判溢出:常阶码,无溢出,结果真值为\(2^{−3}\) × −0.1001111B
范围、精度从小到大,转换过程没有损失
- char -> int -> long -> double
- float -> double
int:表示整数,范围\(-2^{31}\) ~ \(2^{31}\)-1 ,
有效数字32位
float:表示整数及小数,范围±[\(2^{-126}\) ~ \(2^{127}\) × (2−\(2^{−23}\))],有效数字23+1=24位
- int -> float可能损失精度
int向float进行相互强制转换时,由于float的表示范围小于int的表示范围,超出表示的部分会直接被舍弃掉
- float -> int可能溢出及损失精度
float向int进行相互强制转换时,实际上发生了四舍五入,将小数部分进行近似
2.7 数据的存储和排列
由于多字节数据再内存一定是占连续的几个字节空间,对于占用多个字节的数据存在两种存储方式
- 其中最高有效字节被称为MSB,最低有效字节称为LSB
- 大端存储:便于人类阅读,存储地址是递增的,高位有效字节存储在低地址中,依次向上存储低位有效字节,即机器读取数据从高地址向下读取
- 小端存储:便于机器处理,低位有效字节存储在低地址中,依次向上存储高位有效地址,即机器读取数据从低地址向上读取
现代计算机通常按字节编址,即每个字节对应1个地址,通常也支持按字、半字、按字节寻址
- 假设存储字长为32位,则1个字=32bit=4B,半字=16bit=2B,每次访存只能读/写一个字
- 对于一个寻址请求,需要将寻址的单位转换为编址所使用的单位,如按字节编址,存储字长为4B,寻找地址为2字的数据就是寻找8B地址的数据
计算机中各种类型的数据所占用的内存空间是不同的,如每个char占1B,short占2B,int占4B。假设机器存储字长为32位,现一个结构体内包含3个char,3个short,1个int
- 假如最大化利用内存空间,让所有变量都连续存储,对于这个结构体的变量存储会出现边界不对齐的情况。由于每次访存只能读/写一个字,访问int变量的数据访问就需要访问内存两次,效率低
- 如果强制让边界进行对齐,例如3个char后填充1个字节构成一个字,其中一个short后填充半字构成一个字,那么访问这个结构体任何变量只需要访存依一次即可,只是造成部分的空间浪费(拿空间换时间)
本文来自博客园,作者:GK_Jerry,转载请注明原文链接:https://www.cnblogs.com/GKJerry/articles/18319647

浙公网安备 33010602011771号