红魔咖啡馆

头发越掉越多,头发越掉越少

0%

【计算机组成原理】数据的表示和运算

进位计数法

任意进制转十进制

  • 基数:每个数码位用到的不同符号的个数,r进制的基数为r
  • 位权:某位数码在对应位置的权重,任意进制转十进制时r为对应进制数

计算公式: \[ K_nK_{n-1}\dots K_1K_0K_{-1}\dots K_{-m}=\\ K_n\times r^n+K_{n-1}\times r^{n-1}+\dots +K_1\times r^1+K_0\times r^0+K_{-1}\times r^{-1}+\dots +K_{-m}\times r^{-m} \]

二进制和八、十六进制转换

  • 二转八:每三位一组转换对应八进制符号

  • 二转十六:每四位一组转换对应十六进制符号

  • 八转二:每位八进制转换对应三位二进制

  • 十六转二:每位十六进制转换对应四位二进制

十进制转任意进制

整数:

短除法除,除数为r进制的r,余数是对应数码位

最后结果从下往上是高到低位

小数:

每次乘2,得到的小数取整数部分

最后结果从上到下是高到低位

定点数的表示

  • 定点数:小数点位置固定
  • 浮点数:小数点位置不固定(科学计数法)

无符号数

整个机器字长全部二进制位都是数值位,没有符号位

  • 表示范围:n位无符号数为\(0\sim2^n-1\)

有符号数

原码

最高位符号位0/1表示正/负,尾数表示真值的绝对值

  • 若字长n+1位,原码整数表示范围为\(-(2^n-1)\leq x\leq 2^n-1\)

  • 若字长n+1位,原码小数表示范围为\(-(1-2^{-n})\leq x \leq 1-2^{-n}\)

  • 真值0有+0和-0两种形式

反码

正数的反码和原码相同

负数的反码数值位全部取反

表示范围相同,真值0也有两种形式

补码

正数的补码和原码相同

负数的补码=反码尾数取反+1

负数补码转原码:尾数取反+1,或找最右边的1及其右侧同原码,左边同反码

速记方法:由x补码求-x补码:符号位和数值位全部取反,然后+1

补码

补码表示0只有一种表示方式

则定点整数补码10000000就可以表示\(-2^7\),定点小数补码10000000可以表示-1

因此n+1位字长的补码整数的表示范围:\(-2^n\leq x\leq 2^n-1\)

因此n+1位字长的补码小数的表示范围:\(-1\leq x\leq 1-2^{-n}\)

移码

补码基础上将符号位取反

注意移码只能用于表示整数

补码的真值0只有一种形式,表示范围与补码相同

应用:方便比较大小

应用

加减运算

让减法变成加法:

为了让结果能保持在可表示的范围内,我们需要在模\(2^n\)的意义下进行加法操作

在模12的意义下,我们要将需要减的负数找到它等价的一个整数

对于一个负数,它一定能找到一个正数让他俩的绝对值相加等于模数12

如-3和+9在模12的情况下是相同的,他们绝对值相加为12,称互为补数

因此负数需要通过模运算转换,只需要用模数-减数绝对值就可以得到它的补数,其实就是补码,这样就可以让减法操作变为加法

加法操作时,符号位一块参与运算

零扩展与符号扩展

将一个数据拉长bit,多出来的位怎么处理?

对于无符号整数,使用零扩展,多的位补0

对于有符号整数,需要使用符号扩展,多的位与符号位保持一致

运算

加法器

进行加法时,每一位加法都有若干数据:

  • 被加数的本位\(A_i\)与加数的本位\(B_i\)
  • 来自低位的进位\(C_{i-1}\)
  • 本位和\(S_i\)
  • 向高位的进位\(C_i\)

我们发现,当\(A_i\)\(B_i\)\(C_{i-1}\)三个中有奇数个1时,\(S_i\)才为1,否则为0

因此\(S_i=A_i\oplus B_i \oplus C_{i-1}\)

产生进位要求两个本位都是1或两个本位中有一个1且来自低位的进位是1

因此\(C_i=A_iB_i+(A_i\oplus B_i)C_{i-1}\)

用门电路表示如下:

FA

将这个电路封装,得到一位全加器(FA)

把n个FA串联起来,就可以进行两个nbits数的相加’

把这n个FA封装,即为加法器

由于两个输入端允许并行输入nbits,又称并行加法器

缺点:由于进位信息是串行的,位数越多,运算速度越慢,又称串行进位加法器

并行进位加法器

修改一下,加入n位CLA部件,同时传输进位信息,可以弥补缺点

给加法器加入一些标志位,可以判断一些特殊情况

标志位加法器
  • OF:溢出标志,判断带符号数加减运算,1为溢出,0为未溢出

    使用\(C_n\oplus C_{n-1}\)计算是否溢出

  • SF:符号标志,判断带符号数加减运算,1为负,0为正

    取最高位\(S_n\)判断

  • ZF:零标志,1表示结果为0,0表示结果不为0

    取所有bit位取或非,全为0是即为1

  • CF:进位/借位标志,判断无符号数加减运算,1为溢出,0为未溢出

    \(C_{out}\oplus C_{in}\)\(C_n\oplus C_0\)判断

ALU

ALU是运算器的核心,其中加法器是ALU的核心

ALU负责算术运算、逻辑运算、求补码、直送等

ALU
  • 由控制器传输mbit控制信号,表示功能
  • 标志信息通常送入PSW状态字寄存器(有的称为标志寄存器FR)

若ALU支持k种功能,则控制信号位数\(m\geq \lceil \log_2 k \rceil\)

原理

内部靠一个多路选择器接入k个功能电路实现,传入mbit控制信号分别对应使用某个电路

定点数的移位运算

移位运算即改变各个数码位和小数点的相对位置,改变位权

可以快速实现特殊值的乘除法

逻辑移位

逻辑左移:高位移出丢弃,低位补0

对于无符号整数,每左移一位,相当于乘2

注意:若左移丢弃的位为1,发生溢出

逻辑右移:低位移除丢弃,高位补0

对于无符号整数,每右移一位,相当于除2

注意:若右移丢弃的位为1,丢失精度

算术移位

算术左移:高位移出丢弃,低位补0

对有符号整数,每左移一位,相当于乘2

注意:若算术左移前后符号位不同,则发生溢出

算术右移:低位移出丢弃,高位补符号位

对有符号整数,每右移一位,相当于除2

注意:若右移丢弃的位为1,丢失精度

定点数的加减运算

原码的加减

  • 正+正:绝对值做加法,结果为正
  • 负+负:绝对值做加法,结果为负
  • 正+负/负+正:绝对值大的-小的,符号同绝对值大的

减法运算将减数符号取反,转为加法

补码的加减

带着符号位加减即可,算完后计算原码

对于溢出问题,分为下溢与上溢

  • 正+正会发生上溢,得到负数
  • 负+负会发生下溢,得到正数

法一:采用一位符号位

若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时表示有溢出

法二:采用一位符号位,根据数据位进位状况判断

  • 符号位进位\(C_s=0\),最高数值位\(C_1=1\),发生上溢
  • 符号位进位\(C_s=1\),最高数值位\(C_1=0\),发生下溢

\(V=C_s\oplus C_1\),若V=0表示无溢出,若V=1时表示有溢出

法三:采用双符号位

双符号位第一位表示本应得到的符号,第二位表示实际得到的符号

正数符号为00,负数符号位为11

\(V=C_{s1}\oplus C_{s2}\),若V=0表示无溢出,若V=1时表示有溢出

实际存储时还是一个符号位,运算时会复制一个

运算电路

image-20260623105529983

无符号数的加减运算

加法

从最低位开始,按位相加,并往更高位进位

减法

被减数不变,减数全部按位取反、末位+1,减法变加法

从最低位开始按位相加,并往更高位进位

溢出

超出\(0\sim 2^n-1\)即溢出

  • 无符号加法:最高位产生进位为1时,发生溢出
  • 无符号减法:减法变加法,最高位产生进位为0时,发生溢出

无符号整数的乘法

原理

和十进制类似,逐位相乘,错位相加

定义部分积为逐位相乘到当前位的积的结果

  • 两个nbit无符号数乘,可以拆为n轮加法运算
  • 根据乘数的各个bit,决定每轮加法运算是加被乘数还是加全0
  • 注意要错位相加
无符号乘细

电路

  • 首先将被乘数和乘数放入寄存器X Y,乘积寄存器P置0,计数器\(C_n\)初始值置为n(乘数位数)
  • 当乘数和被乘数其中一个为全0,则返回全0
  • 重复n轮加法移位计算,直到\(C_n=0\)
  • 将Y的最低位送人控制逻辑判断
    • 若Y最低位为1,则执行加法,运算结果写回P,进位保存至进位触发器C
    • 若Y最低位为0,则什么也不做
  • 将C P Y 视为整体,逻辑右移一位
  • \(C_n\)减一
  • 结束时,乘法运算结果用\(2n\)位保存
  • 很多架构中,通常仅保留低n位作为乘积结果,可能溢出

溢出

若高n位不全为0,表示发生溢出,将OF位置为1

(CF标志位只用于无符号加减法溢出,乘法溢出都用OF位标志)

解决方法:

  • 不管
  • 在乘法指令后执行一条溢出自陷指令(如x86的INTO指令),该指令会检查OF位,若为1就执行操作系统的异常处理程序

有符号整数的乘法

电路

有符号乘法电路

注:符号位参与运算

  • 首先将被乘数和乘数放入寄存器X Y,乘积寄存器P置0,辅助位置为0,计数器\(C_n\)初始值置为n(乘数位数)

  • 当乘数和被乘数其中一个为全0,则返回全0

  • 重复n轮加减移位运算,直到\(C_n=0\)

    • 将Y的最低位和辅助位2bit送入控制逻辑判断

    • 根据Y的最低位和辅助位判断操作:

      辅助操作
    • 将P Y 和辅助位视为整体,算术右移一位

    • \(C_n\)减一

  • 结束时,乘法运算结果用\(2n\)位保存

  • 很多架构中,通常仅保留低n位作为乘积结果,可能溢出

溢出

若高n+1位不全为0,表示发生溢出,将OF位置为1

解决方法:

  • 不管
  • 在乘法指令后执行一条溢出自陷指令(如x86的INTO指令),该指令会检查OF位,若为1就执行操作系统的异常处理程序

计算机实现乘法的方式

一种改进

之前提到的无符号乘法电路,若实现nbit无符号数相乘,至少需要n个时钟

若改为每轮处理寄存器Y的末尾2bit,仅需n/2个时钟就可以完成运算

阵列乘法器

快速乘法器的一种,可以在一个时钟内完成乘法运算

没有乘法运算电路

可以手动模拟加法和移位操作实现乘法,但是运算速度非常慢

如对于32位,里面有k条指令,所以需要32k个时钟才能实现

无符号整数的除法

中间余数:竖式除法时中间产生的余数

十进制除法上商规则:商×除数的值要尽可能接近但不超过中间余数

二进制除法上商规则:商×除数的值要尽可能接近但不超过中间余数,即如果中间余数>=除数,则商1,否则商0

电路

支持双精度2nbit÷nbit和单精度nbit÷nbit,得到nbit商和nbit余数

若被除数不足2nbit,需要将被除数扩展为2nbit

  • 上商规则:若\(R-Y\geq0\)则商1,否则商0
  • 首先将数据放入寄存器,除数放入Y,被除数放入R Q,完成零扩展
  • 计数器初始值\(C_n=n\)
  • 特殊情况检查:
    • 若除数为0,发生异常,停止除法运算并调用异常处理程序
    • 若|被除数|<|除数|,则商=0,余数=被除数,除法器不再执行
  • 进行n+1轮处理
  • 第1轮特殊处理:
    • 直接上商,若第一位商1,发生商溢出,停止除法运算
    • 直接上商,肉第一位商0,不会商溢出,不必保存这位商,也不\(C_n--\),继续
  • 其余n轮处理:
    • 先左移,空出的位用于上商
    • 上商,背后可能会进行加法/减法
    • 计数器\(C_n--\),当计数器为0时结束运算
  • 寄存器R保存余数,寄存器Q保存商

溢出

只有双精度除法可能发生商溢出

有符号整数的除法

电路

  • 初始化

    • nbit被除数符号扩展为2nbit,放入寄存器R Q
    • nbit除数放入寄存器Y
    • 计数器重置为\(C_n=n\),表示剩余n轮
  • 进行n轮处理,先左移,空出的位置上商

    • 由控制逻辑根据中间余数与除数的符号组合来决定加减法(同号减,异号加)
    • 再根据ALU运算结果(新余数)的符号位决定商1还是0
    • 新老余数相比,符号不变:商1,符号变:商0,新余数写入
    • 若符号位发生变化,余数计数器R会将余数恢复成老余数
  • 计数器\(C_n--\)\(C_n=0\)时除法运算结束

  • \(C_n=0\)时,除法运算结束,R保存余数,Q保存商

    • 若原被除数和除数异号,商Q还需要取补

特殊情况:

  • 如果|被除数|<|除数|,则商为0,余数=被除数,除法器不必再执行
  • 如果除数为0,发生除数为零异常,停止运算并调用异常处理程序
  • 对于补码的单精度除法,仅绝对值最大的负数÷-1才有可能发生商溢出

IEEE 754浮点数

规格化:确保尾数最高位非零数位刚好在小数点前

如二进制小数\(-110.11\),规格化后为\(-1.1011\times 2^2\)

其中:

  • 符号决定正负性
  • 尾数1.1011影响数值精度,位数越多精度越高
  • 阶码2反应小数点的实际位置
  • 基数2表示2进制,k进制默认基数为k

格式

float:

float

double:

double
  • 阶码越大,表示范围越大
  • 尾数越大,表示精度越大

单精度浮点存储

  • 符号:0正1负
  • 尾数:规定小数点位置在23bit前,默认存储规格化尾数,小数点前的1省略
  • 阶码:用移码表示,规定偏置值为127(\(2^{阶码-1}-1\)
  • 基数:不用专门存储,规定为2即可

如何将十进制真值转为偏置值为M的移码:

  1. 将十进制真值+偏置值M
  2. 按无符号整数规则转换为指定位数

双精度浮点存储

  • 符号:0正1负
  • 尾数:规定小数点位置在52bit前,默认存储规格化尾数,小数点前的1省略
  • 阶码:用移码表示,规定偏置值为1023(\(2^{阶码-1}-1\)
  • 基数:不用专门存储,规定为2即可

表示范围

规格化浮点

规格化浮点数:阶码部分不全为0且不全为1的浮点数

  • 阶码:真值取值范围\(-126\sim 127\)

  • 上溢:运算结果大于最大规格化正数称为正上溢,小于绝对值最大的规格化负数时称为负上溢

    正上溢的结果设置为+∞,负上溢为-∞,并设置溢出异常标志位(x86中为OE)

    IEEE 754规定默认不响应浮点数溢出异常,不中断程序

  • 下溢:运算结果在0至绝对值最小的规格化正数之间时称为正下溢,在0至绝对值最小的规格化负数之间时称为负下溢

    下溢时若结果落入非规格化区间,用非规格化浮点数存储,若结果太小,按机器零存储

    若下溢至机器0,设置浮点数下溢异常标志位(x86中为UE)

真值0

非规格化浮点

  • 非规格化正数的阶码要固定解读为最小真值-126

  • 尾数小数点前隐含0而不是1

  • 0除0、负数开根号、∞-∞结果均为NaN

  • 非零数值除以0,结果为±∞

加减运算

步骤

  1. 对阶:对齐为相同数阶码,小阶向大阶对齐

    IEEE规定右移移出的bit至少额外保留三位

  2. 尾数加减:尾数相加减,更可能得到规格化的尾数

  3. 尾数规格化:若未规格化,需要左右规格化

  4. 尾数舍入处理:若规定只保留n位有效尾数,多余的尾数:

    • 直接舍弃
    • 若舍弃部分非0,则入1
    • 四舍五入
  5. 溢出判断:若规定阶码不能超过x,且运算后阶码超出范围则发生溢出

舍入问题

默认就近舍入:

类似零舍一入,即更高位为0舍去,1进位

若三个舍弃位刚好为100,则看前一位,若1+23bit的末位为0,则直接截取多余位,否则进位1

溢出问题

上溢:

浮点数溢出不以尾数溢出判断,尾数溢出可以通过右规纠正

是否溢出主要看指数是否上溢

如:

X=0 11111110 0000000000000000000000

Y=0 11111110 1000000000000000000000

求X+Y

对阶,尾数加减后得到尾数原码为+10.1000000000000000000000

进行规格化,尾数原码变为1.01000000000000000000000,阶码+1变为11111111,此时阶码全1发生上溢,尾数强制置为0

结果为正无穷

下溢:

如:

X=0 00000001 00000000000000000000001

Y=1 00000001 00000000000000000000000

求X+Y

对阶,尾数加减后得到尾数原码为+0.00000000000000000000001

进行规格化,如果尾数继续左移,阶码需要-1,变为00000000,此时变为非规格化浮点数

若当前阶码已经为00000001但尾数需要左规,直接把阶码置为全0,尾数不移位

结果为0 00000000 00000000000000000000001

阶码全0,发生下溢,进入非规格化浮点数区间,则结果为\(2^{-149}\)

数据的存储和排列

大小端

多字节数据在内存里一定是占连续的几个字节,其中最左边为最高有效字节MSB,最右边为最低有效字节LSB

  • 大端法:把MSB存到更低地址部分,LSB存到更高地址部分
  • 小端法:把MSB存到更高地址部分,LSB存到更低地址部分

机器更适于读小端法

边界对齐

现代计算机通常按字节寻址,每个字节对应一个地址

也可以按照字、半字寻址

若存储字长为32位,则一个字=32bit,半字=16bit,每次访存只能读写一个字

按字寻址时,将字的编号左移2就是对应字的地址,按半字是左移1

因此,结构体中如果有多个变量,他们的排布有边界对齐和不对齐两种方式,边界对齐时多出的空间放不下下一个数据类型时,会空出来,这样可以空间换时间,访问一个字和半字时都只需要一次访存