导图社区 第二章 数据的表示和运算
这是一个关于第二章 数据的表示和运算的思维导图,包含数制与编码、运算方法和运算电路、浮点数的表示与运算等。
编辑于2024-01-16 15:53:26第二章 数据的表示和运算
数据的表示和运算
数制与编码
不同进制数之间的相互转换
十进制数转换为任意进制数
除基取余法(整数部分的转换)
乘基取整法(小数部分的转换)
结合r进制数的数值表示公式思考,而不应死记硬背。
原码、补码、反码、移码
原码表示法
正数符号位用 0 表示, 负数符号位用 1 表示, 数值位保持不变。
补码表示法
两种方法来求负数的补码
反码法:当 x ≤ 0 时,符号位为 1,补码数据位等于真值数据位逐位取反,末位加一,这种方法可以通过比较补码和反码公式证明。
扫描法:当 x ≤ 0 时,符号位为 1,对真值数据位从右到左顺序扫描,右起第一个 1 及其右边的 0 保持不变, 其余各位求反。
反码表示法
其符号位和原码相同, 真值为正数时, 反码和原码相同;真值为负数时, 反码数值位为真值数值位取反。
移码表示法
一个真值的移码和补码仅差一个符号位。
定点数表示范围
运算方法和运算电路
运算器
算术逻辑单元(ALU)
ALUop是操作控制端,用来决定ALU所执行的处理功能。
内部原理
所有逻辑、算术运算电路并发运行,多个运算结果分别送入多路选择器输入端,由 AluOp 选择其中一路结果输出。
运算器的基本结构
单总线结构运算器
为避免数据冲突,同一时刻总线上只能传输一个数据,但 ALU 有两个操作数,为此需要在 ALU 输入端设置 LA、LB 两个缓冲寄存器。
完成两个通用寄存器操作数的运算以及结果写回需要 3 个时钟周期
第 1 个时钟周期将通用寄存器的操作数送入 LA,需要给出 Ri→ IB1、IB1 → LA 信号,时钟触发到来时完成操作数送入 LA 的动作。
第 2 个时钟周期需要完成将另一个通用寄存器操作数送入 LB 的操作,要给出 Ri→ IB1、IB1 → LB 信号。
第 3 个时钟周期需要给出运算选择控制信号 AluOp 以及通用寄存器写回控制信号 IB1 → Ri。
双总线结构运算器
为防止 ALU 的输出结果直接送入总线 IB1 而产生数据冲突,在ALU 的输出与 IB1 总线间设置了缓冲寄存器 L 暂存运算结果。
完成运算需要两个时钟周期
第 1 个时钟周期给出 Ri→ IB1、Ri→ IB2 信号来分别输出两个寄存器操作数,同时给出 ALU 运算控制信号 AluOp 来控制数据进行正确的运算,时钟到来时运算结果会自动写入缓冲寄存器 L 中。
第 2 个时钟周期将 L 中的数据送入 IB1 总线,给出 L → IB1、IB1 → Ri信号,在时钟信号的配合下将数据写回通用寄存器中。
三总线结构运算器
旁路器的作用是不通过 ALU 实现通用寄存器之间的数据传输。
三总线结构可以同时给出 Ri→ IB1、Ri→ IB2、AluOp、IB3 → Ri信号,在时钟周期配合下完成运算,整个运算只需要一个时钟周期。
速度是 3 种结构中最快的,且不需要缓冲寄存器,但其通用寄存器堆需要提供两个读端口、一个写端口。
定点数的移位运算
算术移位
算术移位的对象是有符号数,在移位过程中符号位保持不变。
左移一位若不产生溢出,相当于乘以2。
右移一位,若不考虑因移出而舍去的末位尾数,相当于除以2。
算术移位符号位永远是保持不变!
算术移位运算的溢出判断条件是:原码算术左移移丢 1,或补码算术左移移丢与符号相反的位时。
逻辑移位
逻辑移位将操作数视为无符号数。
移位规则:逻辑左移时,高位移丢,低位添0;逻辑右移时,低位移丢,高位添0。
循环移位
定点数的加减运算
补码的加减法运算
在原加法器的Y输入端加入 n 个反向器以实现各位取反的功能,然后加一个2选1多路选择器,用一个控制端Sub来控制,以选择将原码Y输入到加法器还是将Y的各位取反后输入到加法器,并将控制端Sub同时作为低位进位送到加法器。
溢出检测 只有两个符号相同的数相加时才有可能发生溢出。
(1)根据操作数和运算结果的符号位是否一致进行检测。
正正得负、负负得正时溢出。
(2)根据运算过程中最高数据位的进位与符号位的进位是否一致进行检测。
当运算过程中最高数据位的进位与符号位的进位不一致时运算结果发生溢出。
(3)采用双符号位
最高位符号位代表真正的符号。
C 语言运算溢出实例
定点数的乘除运算
定点数的乘法运算
原码一位乘法
补码一位乘法(Booth算法)
定点数的除法运算
原码除法运算(不恢复余数法)
补码除法运算(加减交替法)
C语言中的整数类型及类型转换
有符号数和无符号数的转换
保持位值不变,仅改变了解释这些位的方式。
不同字长整数之间的转换
当大字长变量向小字长变量强制类型转换时,系统把多余的高位部分直接截断,低位直接赋值。
短字长到长字长的转换时,不仅要使相应的位值相等,还要对高位部分进行扩展。
如果原数字是无符号整数,则进行零扩展,扩展后的高位部分用0填充。
否则进行符号扩展,扩展后的高位部分用原数字符号位填充。
本质是补码的符号拓展
数据的存储和排列
数据的“大端方式”和“小端方式”存储
一个 int 型变量i的机器数为01 23 45 67H,其最高有效字节MSB=01H,最低有效字节LSB=67H。
数据按“边界对齐”方式存储
边界对齐方式
边界不对齐方式
一个字节长度的数据不存在边界对齐问题
浮点数的表示与运算
浮点数的表示
浮点数的规格化
左规:当运算结果的尾数的最高数位不是有效位,即出现±0.0…0x…x的形式时,需要进行左规。左规时,尾数每左移一位、阶码减1(基数为2时)。左规可能要进行多次。
右规:当运算结果的尾数的有效位进到小数点前面时,需要进行右规。将尾数右移一位、阶码加1(基数为2时)。需要右规时,只需进行一次。
IEEE754标准
IEEE754 浮点数的加减运算
(1)对阶和规格化过程中,阶码的运算采用移码的加减运算规则。
“小阶向大阶看齐”
(2)尾数的运算采用原码运算规则,且隐藏位要参与尾数运算。
(3)隐藏位参与尾数规格化判断及尾数规格化过程。
若尾数形式为 1.……,则为规格化尾数。
若尾数形式为 1×. ……, 则需要进行向右规格化一次, 即将尾数右移一位, 同时阶码加 1。
若尾数形式为 0.……,则需要进行向左规格化,将尾数左移,尾数每左移 1 位,同时阶码减 1,直到尾数形式为 1.……为止。
(4)舍入处理,IEEE754 中主要有以下舍入方式。
末位恒置 1 法:只要因移位而丢失的位中有一位是 1,就把运算结果的最低位置 1,而不管最低位原来是 0 还是 1。
0 舍 1 入法:当丢失位数的最高位是 1 时将尾数的末位加 1,类似于十进制数的四舍五入。
截断法:直接截取所需位数,丢弃后面的所有位,这种舍入处理最简单。
(5)溢出判断。
浮点运算的溢出可通过阶码的溢出来判断。对 IEEE754 单精度浮点数而言,向右规格化使阶码为全 1(即 11111111,真值为 128)时发生规格化上溢。向左规格化使阶码为全 0 时发生规格化下溢。
对浮点运算而言,当阶码出现溢出时才表示运算结果溢出
可能引起溢出的操作
右规和尾数舍入。数值很大的尾数舍入时,可能因为末位加1而发生尾数溢出,此时需要通过右规来调整尾数和阶。右规时阶加1,导致阶增大,因此需要判断是否发生了指数上溢。
左规。左规时阶减1,导致阶减小,因此需要判断是否发生了指数下溢。其判断规则与指数上溢类似,左规一次,阶码减1,然后判断阶码是否为全0来确定是否指数下溢。
指数上溢和指数下溢
若一个正指数超过了最大允许值(127或1023),则发生指数上溢,产生异常。
若一个负指数超过了最小允许值(-126或-1022),则发生指数下溢,通常把结果按机器零处理。
C语言中的浮点数类型
int、float、double 之间强制类型转换
double→float
大数转换时可能发生溢出,高精度数转换时会发生舍入。
float/double→int
小数部分会舍入,大数转换时可能会溢出。
float→double
由于 double 型数据的尾数、 阶码宽度都比 float 型大, 因此其表示范围更大、精度更高,转换后的 double 型数据与原 float 型数据完全相等。
int→float
两种类型都是 32 位,所表示的状态数是一样的,二者在数轴上表示的数据并不完全重叠。
float 型用其中一部分状态表示了更大的整数和小数。 int 型中一些比较大的整数无法用 float 型精确表示。
浮点数尾数连隐藏位在内一共 24 位, 当 int 型数据的 24 ~ 31 位数据非 0 时, 无法精确转换成 24 位浮点数的尾数,此时会发生精度溢出,需要进行舍入处理。
int→double
浮点数尾数字段为 53 位,可以精确表示所有 32 位整数。