2018-2019-1 20189206 《深入理解计算机系统》第二章学习笔记

2018-2019-1 20189206 《深入理解计算机系统》第五周学习总结

教材学习内容总结

本章主要研究三种重要的数字表示,分别是无符号编码、补码编码和浮点数编码。其中,无符号编码表示大于或等于零的数字,补码编码用来表示有符号整数,浮点数编码是科学计数法的以2为基数的版本。

第二章 信息的表示和处理

信息存储的方式

  1. 最小可寻址的内存单位————8位的块,也称为字节
  2. 机器级程序将内存视为一个非常大的数组,称为虚拟内存
  3. 内存的每个字节都由唯一的数字来表示,称为地址

十六进制表示方式

  1. 一个字节的
    对应的二进制表示为 \(00000000_2 至 11111111_2\)
    对应的十进制表示为 \(0_{10} 至 255_{10}\)
    对应的十六进制表示为 \(00_{16} 至 FF_{16}\)(以0x或者0X开头的数字为十六进制表示)
  2. 特殊的转换方法

    当值x是2的非负整数的n次幂时即 \[x=2^n\] 可以将x写成1后面加n个0的形式。
    当n表示为 n=i+4j 时(0<=i<=3),x对应的十六进制数字可以写成1、2、4、8后面跟J个0
    例如: \[ 512 = 2^9 \] 知 n=1+2*4 故2048对应的16进制是 0x200

字数据大小

  1. 每个计算机都有一个字长,用来指明指针数据的标称大小。 字长决定的最重要的系统参数就是虚拟地址空间的最大大小。对于一个字长为w的机器,虚拟地址的范围为\[ 0 至 2^w -1 \]程序最多访问2^w个字节。
  2. 多字节对象被存储为连续的字节序列,对象的地址为使用字节中最小地址
    • 大端法:最高有效字节存储在前面(即先存储最高有效字节)
    • 小端法:最低有效字节存储在前面(先存储最低有效字节)
    • 假设0x01234567
      • 大端法存储为 01 23 45 67 (地址从左至右增大)
      • 小端法存储为 67 45 23 01 (地址从左至右增大)
  3. linux32 Windows和linux64 均为小端机器,可以记为阅读顺序和存储顺序相反。

下面show_bytes函数的作用是打印出每个以十六进制表示的字节,其中输入是一个字节序列的地址。

void show_bytes(byte_pointer start,size_t len)
{
    size_t i;
    for(i=0;i<len;i++)
    {
        printf("%.2x",start[i]);
    }
    printf("\n");
}

void show_int(int x)
{
    show_bytes((byte_pointer)&x,sizeof(int));
}

实现的功能就是输出int型每个字节对应的十六进制表示。

布尔代数

    布尔运算     逻辑运算    命题逻辑
       ~          NOT        ┐
       &          AND        ∧
       |          OR         ∨
       ∧         异或        ⊕
  • 位级运算的常用用法是实现掩码运算,掩码表示从一个数中选出的位的集和。
    x & 0xFF 得到的结果就是x最低有效字节组成的值,其余字节被置0,之后表达式~0 得到的结果就是全为1 的掩码。

【注】注意区分C语言中的逻辑运算与位级运算

C语言的逻辑运算是|| &&和!,分别对应命题逻辑中的OR、AND和NOT运算。逻辑运算认为所有的非零值都为真,参数零表示假,运算结果只由0和1。

逻辑运算中如果第一个参数求值就能确定表达式的值,逻辑运算不会对第二个参数求值

位移运算

  • 位移运算分为左移和右移
    • 左移 X向左移,丢弃最高的k位,并在右端补0
    • 右移 X向右移,丢弃最低的k位
      • 算数右移 在左端补k个最高有效位的值
      • 逻辑右移 在左端补0

几乎所有的编译器/机器组合都会对有符号数使用算数右移,而对于无符号数,右移必须是逻辑右移。

整数表示

无符号数只能表示非负数,而补码编码能够表示负数、0和正数。

  • 无符号数的编码

    • 无符号数的定义
      对于向量 \[ \vec{x} = [x_{w-1},x_{w-2},\cdots,x_0] \]

      \[B2U_w (\vec{x}) = \sum_{i=0}^{w-1}x_i2^i\]

    • 无符号数所能表示的值的范围
      [0 0 …… 0] 到 [1 1 …… 1]即
      \[UMax_w = \sum_{i=0}^{w-1}2^i = 2^w-1\]

    • 无符号编码的唯一性
      函数B2U是一个双射,将每一个长度为w的位向量,映射为0~2^w-1之间的唯一一个值,这种映射是一一对应的关系,即可以反向操作。

  • 补码编码
    最常见的有符号数的计算机表示方式就是补码形式,这种形式下,将字的最高有效位解释为负权。

    • 补码编码的定义

    对于向量 \[ \vec{x} = [x_{w-1},x_{w-2},\cdots,x_0] \]

    \[B2T_w (\vec{x}) = -x_{w-1}2^{w-1} + \sum_{i=0}^{w-1}x_i2^i\]

    最高有效位称为符号位,符号位为1时,表示值为负数;符号值为0时,值为非负。

    • 补码所能表示的范围

    它能表示的最小值是[1 0 …… 0] 其整数值为 \[TMin_w = -2^{w-1} \]
    最大值为[0 1 …… 1] 其整数值为\[TMax_w = \sum_{i=0}^{w-1}2^i = 2^w-1\]

    • 补码有着与无符号数相同的双射函数
    • 最大无符号数刚好比补码的最大值的两倍大一\[UMax_w=2TMax_w + 1 \]

有符号数和无符号数之间的转换

  • 强制类型转换的结果保持位不变,只是改变了解释这些位的方式。处理同样字长的有符号数和无符号数之间的转换一般规则是:数值可能会改变,但是位模式不变

  • 补码转换为无符号数

对满足\[TMin_w\leq x \leq TMax_w \]的x有:
\[T2U_w(x) =\begin{cases} x+2^w & x <0 \\\ x & x \geq 0 \end{cases}\]

从以上表达式可以看出,将一个有符号数转为它相应的无符号数时,负数就被转换成了大的整数,非负数则会保持不变。

  • 无符号数转换为补码

对满足\[0 \leq u \leq UMax_w \]的x有:
\[U2T_w(u) =\begin{cases} u & x \leq TMax_w \\\ u-2^w & u>TMax_w \end{cases}\]

从以上表达式可以看出,讲一个无符号数转换为补码时,U2T把大于2^w-1的数转化成了负数。

从上述两个公式可以看出,对于在范围\[ 0 \leq x \leq TMax_w \]的范围内的数字有着相同的补码和无符号数表示。对于这个范围以外的数需要加上或者减去2^w

  • C语言中,当执行一个运算时,它的一个运算数是有符号的,另一个运算数是无符号的,那么C语言会将有符号数强制类型转换为无符号数,并假设这两个数都是非负的。

扩展一个数字位的表示

  1. 将无符号数转换为一个更大的数据类型——零扩展
  2. 将补码转换为一个更大的数据类型——符号扩展(添加最高有效位的值)

截断数字

  1. 截断无符号数

\[\vec{x} = [x_{w-1},x_{w-2},\cdots,x_0]\] 现截断该位向量k位的结果是\[x' = x mod 2^k\]

  1. 截断补码数值
    \[\vec{x} = [x_{w-1},x_{w-2},\cdots,x_0]\] 现截断该位向量k位的结果是\[x' = U2T_k(x mod 2^k)\]即把最高位的权重从正变为负。

整数运算

  • 无符号加法
    定义无符号数加法,该操作是把整数和x+y截断为w位得到的结果,再把这个结果看作是一个无符号数。可以被看作是一种形式的模运算
    对于x、y满足\[ 0 \leq x,y<2^w \]有:
    \[x + y =\begin{cases} x+y & x+y \leq 2^w \\\ x+y-2^w & 2^w \leq x+y <2^{w+1} \end{cases}\]

当x+y的结果s小于x或者小于y的时候,可以判定无符号数的加法出现了溢出。

  • 无符号数求反

模数加法形成了一个阿贝尔群,对于每个x值必定有有一个加法逆元。
对于满足\[ 0 \leq x <2^w \]的任意x值,其无符号加法逆元为
\[- x =\begin{cases} x & x=0 \\\ 2^w-x & x>0 \end{cases}\]

  • 补码加法
    对于满足\[-2^{w-1} \leq x,y \leq 2^{w-1}-1 \]的整数x和y 有
    \[x + y =\begin{cases} x+y-2^w & 2^{w-1} \leq x+y & 正溢出 \\\ x+y & -2^{w-1} \leq x+y <2^{w-1} &正常\\\ x+y+2^w & x+y<-2^{w-1} & 负溢出 \end{cases}\]

  • 补码的非
    对于满足\[ TMin\_w \leq x <TMin\_w \]的任意x值,其补码的非为
    \[- x =\begin{cases} TMin\_w & x=TMin\_w \\\ -x & x>TMin\_w \end{cases}\]

  • 无符号和补码乘法
    将一个数截断w就等价于计算该值的模2^w
    对于无符号和补码乘法来说,乘法运算的位级表示都是一样的。

  • 乘以常数

由于在大多数机器上,整数乘法的指令需要10个或者更多的时钟周期,其他整数运算只需要1个时钟周期。编译器使用了优化,试着用位移和加法的运算组合代替乘以常数因子的乘法。
原理: 设x的位模式为 \([x_{w-1},x_{w-2},\cdots,x_0]\)表示无符号整数,那么对于任何$k \leq 0 $都认为 \([x_{w-1},x_{w-2},\cdots,x_0,0,0,\cdots,0]\) 给出了 \(x*2^k\) 的w+k位的无符号表示,右边增加了k个0。
可以看出,左移一个数值相当于执行一个与2的幂相乘的无符号乘法

例如:一个程序包含表达式 x*14 利用 $14 =2^3+2^2+2^1 $ 可以将该乘法重写(x<<3)+(x<<2)+(x<<1),将一个乘法替换为位移和两个加法。
或者利用 $14 =2^4-2^1 $ 重写成 (x<<4)-(x<<1)

  • 除以2的幂
    • 除以2的幂的无符号除法
      假设有无符号数值x和k,且 $0 \leq k <w $ 则表达式 x>>k 产生结果\(\lfloor x/2^k \rfloor\)
    • 除以2的幂的补码除法
      假设有补码数值x和无符号数值k,且 $0 \leq k <w $ 则表达式执行算术位移 x>>k 产生结果\(\lfloor x/2^k \rfloor\)

浮点数

  • 二进制小数
    表示方法:$ b_m b_{m-1} \cdots b_1 b_0.b_{-1} b_{-2} \cdots b_{-n} $
    这个表达描述的定义如下:
    \[b = \sum_{i=-n}^{m}2^i*d_i \]

  • IEEE浮点表示
    • 浮点标准用\[ V= (-1)^s * M * 2^E \] 来表示一个数
      • 符号:s决定了这个数是负数(s=1)还是正数(s=0)
      • 尾数:M是一个二进制小数,范围是1~2-ε 或者 0~1-ε
      • 阶码:E的作用是对浮点数加权,这个权重是2的E次幂
    • 将浮点数的位表示划分为3个字段,分别对这些值编码
      • 一个单独的符号位s
      • k位的阶码字段\(exp=e_{k-1} \cdots e_1 e_0\)编码阶码E
      • n位的小数字段$frac=f_{n-1} \cdots f_1 f_0 $编码尾数M
    • 规格化的值
      • exp的位模式不会全为0或全为1 阶码字段被表示为以偏置形式表示的有符号整数。E= e-bias e为无符号数 \(bias=2^{k-1}-bais\)
      • 小数字段frac,尾数定义为M=1+f
    • 非规格化的值
      • 阶码E全为0时是非规格化的形式,此时 E=1-Bias 尾数值M=f
    • 特殊值
      • 阶码全为1时,得到的值表示无穷

【注】浮点运算只由有限的范围和精度,并且不遵守结合律。

总结

本章重点在于用数学公式准确定义出计算机中使用的几种数据类型,内容很多,需要好好总结和复习。通过直接操作数字级的位表示,得到了几种算数运算的方式。针对不同的机器,变量类型存储的大小也不同、存储方式不同,为了能使编写的程序在全部范围内正确工作,可以实现跨越不同的机器、操作系统和编译器的组合,对于这种数学原理的学习是十分重要的。
第二章主要从信息存储的方式、整数表的方法(无符号编码、补码编码)以及相关操作、整数运算(无符号运算、补码运算)、浮点数(两种表示方式)等方面介绍了数据的存储表示方式,进行计算的结果等内容。

猜你喜欢

转载自www.cnblogs.com/zz-1226/p/9887885.html
今日推荐