csapp第二章 信息的处理和表示(2)

布尔代数

弄清楚布尔代数的运算和逻辑运算以及离散数学中的命题逻辑的一一对应关系。

位向量

固定长度为w,由0和1组成的串

位向量的运算可以对应为参数的每个对应元素的运算

任意a a^a=0

位向量表示有限集合,则布尔运算& 和|对应集合的交并

c语言中的位级运算

位级运算的常见用法是实现掩码运算,掩码是一个位模式,表示从一个字中选出的位的集合

x&0xFF生成一个由最低有效字节生成的值,其他的字节被置为0

求补时要想到利用异或运算 对1异或可得其补,对0异或可得本身 见p39练习12

c中的逻辑运算

c中的逻辑运算符|| && ! 对应命题逻辑中的OR AND NOT 注意区分逻辑运算和位级运算

  1. 第一个区别 逻辑运算所有非0参数都表示为true 参数0才表示false ,按位运算只有在参数被限制为0或1时才和对应的逻辑运算有相同的行为
  2. 第二个区别 如果对第一个参数求值就能确定表达式的结果,那么逻辑运算符不会对第二个参数求值

c中的移位运算(x<<k)(x>>k)

左移:向左移动k位,丢弃最高的k位,在右端补k个0

逻辑右移:在左端补k个0,右移k位(无符号数必须逻辑右移)

算术右移:在左端补k个最高有效位的值

java中

x>>k会将x算术右移k个位置

x>>>k会对x做逻辑右移

整数表示

书中记述的比较详细,这里仅列出一部分要点

整型数中无符号数的编码,了解函数B2Uw(x的位模式)

补码编码的方式,了解函数B2Tw(x的位模式)

​ 补码运算的一些特殊地方,0表示2非负数,所以最高位是1的数会比最高位是0的数多一个 ,也就是负数会比正数多一。

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

​ 强制类型转换结果保持位值不变,仅仅改变解释这些位的方式

换句话说,同一个数据,只是解读方式不同 。 补码和无符号数之间的关系,举例16位位模式0xCFC7的补码表示是-12345,无符号表示位53191,而两者绝对值相加得到65536=2的16次方。

补码转换为无符号数,使用函数T2Uw(x)

x<0时,函数值为x+2^w

x>0时,函数值为x

无符号数转换位补码,调用函数U2Tw(u)

u<=TMaxw,函数值为u

u>TMaxw,函数值位u-2^w

扩展一个数字的位表示

对于一个无符号数转为更大的数据类型只需要简单地在表示的开头添加0,这种运算称为零扩展

对于有符号的数,即补码进行符号扩展(sign extension),就是添加最高有效位的值

整数运算

无符号加法

x+y=(x+y)mod2^k`

溢出会舍去

阿贝尔群,群论。

补码加法

大多数计算机使用同样的机器指令来执行有符号和无符号之和。

img

x(有符号+)y= U2T(T2U(x+y) mod 2^w)

  • 先计算x+y
  • 将x+y转换为无符号类型z。
  • p=z mod 2^w
  • 附.(或者直接对x+y的二进制表示进行截断得到p)
  • 将p用有符号类型表示

  • 正溢出,正常,负溢出。

    img

img

补码的非

  • 因为正负区间的不一致
  • 所以最小的那个负数的相反数逆元还是最小的那个负数。
  • 对于任意整数x-x~x+1得到的结果完全一样。

无符号乘法

只取低w位表示的值,其余截断

补码乘法

对于无符号和补码乘法,乘法运算的位级表示都是一样的,是同一条指令。无符号和补码相乘出来的两个数的低W位 永远相等。证明见书。

img

乘常数

因为乘法速度太慢,机器可能会用(加法,减法,移位)来代替乘法。

img

除以2的幂

对于无符号类型或整数,直接右移不会有任何问题。

对于负数,最后的值为-48.3,会舍入成 -49,而不是-48.

浮点数

一个二进制串分为三部分。

  1. 符号位,1位,决定正负。
  2. 阶码 E,对浮点数加权,2^E。C语言里float,8位;double, 11位。
  3. 尾数 M,二进制小数,计算分情况。C里float, 23位;double, 52位。

计算根据阶码分为三种,规格化、非规格化、特殊值,float为例:

  1. 规格化,E各位不全为0也不全为1,即e!=0 && e!=255。E = e - 127。所以E的范围其实是[-126, 127] 。此时 M = m + 1。所以最后绝对值为 M·2^E = (m+1)·2^(e-127)。
  2. 非规格化,全为0,e=0。E = 1 - 127. M = m。所以最后绝对值为 M·2^E = m·2^(-126)。当m取最小值2^(-23)时,这也是float能够表示的最小非零数,2^(-149)。
  3. 特殊值,全为1,e=255。当m=0时,根据符号位分别得到+∞和-∞。当m!=0时,得到NaN,意为 Not a Number。

至于为什么e=0时,M=m而不是M=m+1?
此处结合e=0时,E也不是0-127,而是1-127,正好等于规格化的最小e,也是1-127。这个在非规格化向规格化过渡的时候,相同的指数值,保证整个f的值会随着m的增长而增大(线性的)。因此,对浮点数排序时,也可以像整数一样,直接比较其二进制位,从高位开始比较。

这个设计很有意思,假如在非规格化时,E=0-127,M=1+m,非规格化最大数为E=-127,M=1+(2^23-1)/2^23,f=2^E·M=2^(-126)-2^(-150)。规格化最小数为E=1-127,M=1+0,f’=2^(-126)。(哎?f’>f,额这是哪里算错了吗?)f’-f=2^(-150).

真实情况是,非规格化最大数为E=1-127,M=(2^23-1)/2^23,f=2^(-126)-2^(-149),规格化最小数仍然是f’=2^(-126).f’-f=2^(-149)。这正是相邻的两个非规格化数的间隔2^(-126)·2^(-23)=2^(-149)。也就是说IEEE的这种设计保持了在非规格化和规格化数之间的一个平滑过渡。

​ 强转与舍入

  • int转为float,不会溢出,但是可能被舍入,毕竟都只有2^32个状态,能表达的总信息量是一定的。如2^24+1和2^24强转为float后,值为2^24.000000。舍入的时候会有一种特殊情况,称为向偶数舍入,在非有效位值正好是两个可能值的中间值时,我们倾向于通过取舍,使得有效位的最后一位为0.
  • double转float, 可能溢出为-∞或+∞.
  • float和double转int,向零舍入。如果出现溢出,则值会变成0b1000 0000,也就是-Min。

csapp第一章

收获:

  1. 程序的生命周期:

    从熟悉的利用c语言编写的hello.c文本文件,经过预处理 编译 汇编 链接阶段生成可执行目标文件 然后保存存储到磁盘上,当在shell里键入./ hello后 shell程序将字符读入寄存器,再存放到内存 敲下回车键 shell知道已经结束输入 加载可执行的hello 程序中的代码和数据从磁盘复制到内存 通过dma省去数据经过处理器的过程 当hello中的代码和数据被加载到内存 处理器开始执行main程序的机器语言指令,这些指令将字符串中的字节从内存复制到寄存器 再复制到显示设备

  2. 抽象的使用

    文件是对io的抽象(网络都可以看成是文件)

    虚拟内存是对程序存储器的抽象

    进程是对正在运行的程序的抽象

    虚拟机是对整个计算机的抽象

3.程序的生命周期说明了系统花费大量时间在内存,io和cpu之间复制数据,由此将存储设备划分层次结构

4.并发和并行

使计算机做的更多,运行的更快

并发:指一个同时具有多个活动的系统

并行:用并发来使一个系统运行的更快

理解:并行强调同一时刻发生,并发表示该系统具有执行多个活动的能力,但不是在同一时刻 并发事件不一定要在同一时间发生,并行只同时发生的两个并发事件,具有并发的含义

5文件

文件就是字节序列 每个IO设备,包括磁盘,键盘,显示器,甚至网络都可以看成文件

6进程和线程

操作系统提供的假象:程序独占处理器,内存和io设备

处理器看上去不断的执行程序中的指令

处理器并发执行进程,即一个进程的指令和另一个的进程的指令交错执行

上下文的概念,操作系统保持跟踪程序所需的所有状态信息,这种状态即上下文。操作系统将控制权从一个进程交给另一个进程时,发生上下文转换:保存当前进程上下文,恢复新进程的上下文,控制权交给新进程

进程由多个称为线程的执行单元组成 线程运行在进程的上下文中,共享代码和全局数据

7 虚拟内存

为进程提供的假象:每个进程独占内存,每个进程看到的内存都一样,称为虚拟地址空间

基本思想是把一个进程虚拟内存的内容存储到磁盘上,然后用内存作为磁盘的高速缓冲存

注:上一级的存储器作为低一级的存储器的高速缓存

问题:

并行必须要多核吗?

并行需要多核,多个线程**同时**在多个cpu上运行