深入理解计算机系统:第1-2章

第1章 计算机系统漫游

图1 编译系统

GCC(GNU Compiler Collection)

预处理 -E
只执行到预编译,默认输出至控制台
gcc -E main.c -o main.i

编译 -S
只执行到编译,默认生成汇编文本文件,后缀.s
gcc -S main.i
gcc -S main.c

汇编 -c
只执行到汇编,默认输出二进制目标文件,后缀.o
gcc -c main.s
gcc -c main.c

链接
生成可执行文件
gcc main.o -o main
gcc main.c -o main
// 自动优化编译
gcc -O main.c -o main


程序编译

预处理: 加载头文件至原始程序;
编译: 编译器将文本文件hello.i翻译成汇编程序文本文件hello.s;
汇编: 汇编器将汇编程序文件翻译成机器语言指令;
链接: 链接将已经编译好的目标文件(后缀.o)合并,生成可执行文件;


程序运行

获取指令: 键盘输入"./hello",字符读入寄存器,再存放至内存;
加载文件: 利用直接存储器存取技术(DMA),目标文件可不通过CPU直接从磁盘加载到主存;
程序执行: 机器指令从主存复制到寄存器并执行,执行结果从寄存器复制到显示设备,打印输出;


高速缓存cache

内存读取速度比磁盘读取快约1000万倍;
寄存器读取速度比主存读取快约100倍;
高速缓存L1和L2是一种静态随机访问存储器(SRAM)。L1高速缓存读取速度约等于寄存器,比L2高速缓存快5倍; L2高速缓存读取速度比主存读取快5~10倍;


操作系统

基本功能

防止硬件被失控的程序滥用;
向应用程序提供简单一致的机制控制复杂的低级硬件设备;
注:基于进程、虚拟内存、文件实现

进程

进程是操作系统对正在运行的程序的一种抽象。
并发运行是指一个进程的指令和另一个进程的指令交错执行,多个进程同时活动。一个CPU通过上下文切换实现并发执行多个程序。

线程

一个进程由多个线程组成,每个线程都运行在进程的上下文中,共享同样的代码和数据。

虚拟内存和虚拟内存空间

虚拟内存是主存和I/O设备的抽象,它为每个进程提供一种独立占用内存的假象。
每个进程看到的内存都是一致的,称为虚拟地址空间。
虚拟地址空间包括:只读的代码和数据、读/写数据、堆、共享库、栈、内核虚拟内存。

文件

文件就是字节序列,每个I/O设备,包括磁盘、键盘、显示设备,甚至网络都可看为文件。

并发与并行

并发是同时具有多个活动的系统,并行是用并发使系统运行的更快。

线程级并发: 超线程,又称为同时多线程,允许单CPU执行多个控制流的技术;

指令集并发: 早期处理器需3~4个机器周期处理一条指令,现在CPU利用流水线技术,将一条指令划分为不同步骤。这些阶段可并行操作,用来处理不同指令的不同部分。若处理器一个机器周期可执行一条以上的指令,称之为超标量处理器。

单指令、多数据并行: 特殊的硬件结构允许一条指令产生多个并行执行的操作,称之为单指令、多数据(SIMD)并行。如并行对8对单精度浮点数做加法。



第2章 信息的表示和处理

2.1 信息存储

字长

字长指明指针数据的标称大小,虚拟地址以一个字长编码。字长决定了最大的寻址空间,即决定了虚拟地址空间的有效值。
如对于32位计算机,最大寻址空间 2 32   b y t e s = 4   G B \sf{2^{32}\,bytes = 4\,GB} 232bytes=4GB

寻址和字节顺序

大端/小端法分别以最高/最低有效字节在最前面(地址较小)的方式存储数据。
假设 i n t \sf{int} int型变量 x \sf{x} x位于地址 0 x 100 \sf{0x100} 0x100处,其十六进制值为 0 x 12345678 \sf{0x12345678} 0x12345678,以大端法和小端法的存储格式分别如下:

深入理解计算机系统:第1-2章_第1张图片

移位运算

逻辑右移左端补0,算数右移左端补符号位。
如有符号数-8,补码表示为1111 1000,算数右移1位(等价于除2),得到1111 1100,即-4。


2.2 整数表示

编码

对向量 x ⃗ = [ x w − 1 , x w − 2 , ⋯   , x 0 ] \vec x=[x_{w-1},x_{w-2}, \cdots, x_0] x =[xw1,xw2,,x0],则位向量到整数的映射

无符号编码( b i n a r y   t o   u n s i g n e d \sf{binary \, to \, unsigned} binarytounsigned):
B 2 U w ( x ⃗ ) = ∑ i = 0 w − 1 x i 2 i B2U_w(\vec x)=\sum_{i=0}^{w-1} x_i2_i B2Uw(x )=i=0w1xi2i

反码编码( b i n a r y   t o   t w o ′ s   c o m p l e m e n t \sf{binary \, to \, two's \,complement} binarytotwoscomplement),正数反码与原码相同,负数反码是对其原码除符号位逐位取反,则:
B 2 O w ( x ⃗ ) = − x w − 1 ( 2 w − 1 − 1 ) + ∑ i = 0 w − 2 x i 2 i B2O_w(\vec x)=-x_{w-1}(2^{w-1}-1) + \sum_{i=0}^{w-2} x_i2_i B2Ow(x )=xw1(2w11)+i=0w2xi2i

补码编码( b i n a r y   t o   t w o ′ s   c o m p l e m e n t \sf{binary \, to \, two's \,complement} binarytotwoscomplement),正数补码与原码相同,负数补码为其补码加1,则:
B 2 T w ( x ⃗ ) = − x w − 1 2 w − 1 + ∑ i = 0 w − 2 x i 2 i B2T_w(\vec x)=-x_{w-1}2^{w-1} + \sum_{i=0}^{w-2} x_i2_i B2Tw(x )=xw12w1+i=0w2xi2i

类型转换

对整数 x x x,其向量表示 x ⃗ = [ x w − 1 , x w − 2 , ⋯   , x 0 ] \vec x=[x_{w-1},x_{w-2}, \cdots, x_0] x =[xw1,xw2,,x0],有以下转换:

补码转为无符号数
B 2 U w ( x ⃗ ) − B 2 T w ( x ⃗ ) = x w − 1 2 w B2U_w(\vec x) - B2T_w(\vec x)=x_{w-1}2^w B2Uw(x )B2Tw(x )=xw12w,且 B 2 T w ( x ⃗ ) = x B2T_w(\vec x)=x B2Tw(x )=x,得 B 2 U w ( x ⃗ ) = x w − 1 2 w + x B2U_w(\vec x)=x_{w-1}2^w+x B2Uw(x )=xw12w+x,得
T 2 U w ( x ) = B 2 U w ( x ⃗ ) = x w − 1 2 w + x T2U_w(x)=B2U_w(\vec x)=x_{w-1}2^w+x T2Uw(x)=B2Uw(x )=xw12w+x

无符号数转为补码
B 2 U w ( x ⃗ ) − B 2 T w ( x ⃗ ) = x w − 1 2 w B2U_w(\vec x) - B2T_w(\vec x)=x_{w-1}2^w B2Uw(x )B2Tw(x )=xw12w,且 B 2 U w ( x ⃗ ) = x B2U_w(\vec x)=x B2Uw(x )=x,得 B 2 T w ( x ⃗ ) = x − x w − 1 2 w B2T_w(\vec x)=x-x_{w-1}2^w B2Tw(x )=xxw12w,得
U 2 T w ( x ) = B 2 T w ( x ⃗ ) = x − x w − 1 2 w U2T_w(x)=B2T_w(\vec x)=x-x_{w-1}2^w U2Tw(x)=B2Tw(x )=xxw12w

C语言中有符号数与无符号数运算时,有符号数会强制转为无符号数,比较大小时可能出错!负值赋给无符号数,自动执行T2U转换。

short v1 = -12345;
unsigned short u = (unsigned short)v1;
short v2 = (short)u;
cout << u << ' ' << v2 << endl;
//53191 -12345

// 无符号数与有符号数计算,有符号数会强制转为无符号数
unsigned int a = 0;
int b = -1;
cout << (a > b) << endl;
// 0
// 无符号数溢出
cout << a - 1 << endl;
// 4294967295

位扩展与截断

无符号数扩充位使用零扩展,补码数扩充位使用符号扩展。
位扩展时,先转换大小再转换符号,如short v = -12345,则(unsigned)v = 4294954951。
无符号数截断时,丢弃截断位;补码数截断时,丢弃截断位并将结果进行 U 2 T k U2T_k U2Tk转换。

short v = -12345;
unsigned u1 = v;
unsigned u2 = (unsigned)(int)v;
unsigned u3 = (unsigned)(unsigned short)v;
cout << u1 << ' ' << u2 << ' ' << u3 << endl;
// 4294954951 4294954951 53191
cout << (short)u1 << ' ' << (short)u2 << ' ' << (short)u3 << endl;
// -12345 - 12345 - 12345

int v1 = (1<<16) + (1<<15);
cout << short(v1) << endl;
// -32768


2.3 整数运算

无符号数加法
x   + w u   y = { x + y , x + y < 2 w 正 常 x + y − 2 w , x + y ≥ 2 w 溢 出 x \, +_w^u \, y= \begin{cases} x+y, & \text x + y < 2^w & \quad正常\\ x + y - 2^w, & \text x+y \geq 2^w & \quad溢出 \end{cases} x+wuy={x+y,x+y2w,x+y<2wx+y2w

补码加法
x   + w t   y = { x + y − 2 w , x + y ≥ 2 w − 1 正 溢 出 x + y , - 2 w − 1 ≤ x + y < 2 w − 1 正 常 x + y + 2 w , x + y < − 2 w − 1 负 溢 出 x \, +_w^t \, y= \begin{cases} x+y-2^w, & \text x + y \geq 2^{w-1} & \quad正溢出 \\ x + y, & \text -2^{w-1} \leq x +y < 2^{w-1} & 正常 \\ x+y+2^w, & \text x+y< -2^{w-1} & \quad负溢出 \end{cases} x+wty=x+y2w,x+y,x+y+2w,x+y2w1-2w1x+y<2w1x+y<2w1

无符号数乘法
x ∗ w u y = ( x ⋅ y ) m o d    2 w x *_w^u y = (x \cdot y) \mod 2^w xwuy=(xy)mod2w

补码乘法
x ∗ w t y = U 2 T w ( ( x ⋅ y ) m o d    2 w ) x *_w^t y = U2T_w((x \cdot y) \mod 2^w) xwty=U2Tw((xy)mod2w)

无符号和补码乘法的位级等价性
x ′ = T 2 U w ( x ) = x + x w − 1 2 w x'=T2U_w(x)=x+x_{w-1}2^w x=T2Uw(x)=x+xw12w y ′ = T 2 U w ( y ) = y + y w − 1 2 w y'=T2U_w(y)=y+y_{w-1}2^w y=T2Uw(y)=y+yw12w,故
( x ′ ⋅ y ′ ) m o d    2 w = [ ( x + x w − 1 2 w ) ⋅ ( y + y w − 1 2 w ) ] m o d    2 w = [ x ⋅ y + ( x w − 1 y + y w − 1 x ) 2 w + x w − 1 y w − 1 2 2 w ] ) m o d    2 w = ( x ⋅ y ) m o d    2 w \begin{aligned} (x' \cdot y') \mod 2^w & = [(x+x_{w-1}2^w) \cdot (y+y_{w-1}2^w)] \mod 2^w \\ & = [x\cdot y + (x_{w-1}y+y_{w-1}x)2^w+x_{w-1}y_{w-1}2^{2w}]) \mod 2^w \\ & = (x \cdot y) \mod 2^w \end{aligned} (xy)mod2w=[(x+xw12w)(y+yw12w)]mod2w=[xy+(xw1y+yw1x)2w+xw1yw122w])mod2w=(xy)mod2w
带权重 2 w 2^w 2w 2 2 w 2^{2w} 22w的项取模运算均为0。

乘法优化
整数乘法指令相当慢,约10个机器周期,一般分解为加法、减法、位级运算和移位运算。
对于乘法x*K,K的二进制是一组0和1交替的序列,如14可写为[0…01110]。
考虑一组从位置n到m的连续1(对于14,n=3,m=1),可用下列方式计算乘积:
\quad 形式A:(x << n) + (x << (n-1) + ··· + (x << m))
\quad 形式B:(x << (n + 1) - (x << m))
如x * 14 = (x << 4) - (x << 1),只需要两次移位和一次减法。

整除舍零偏置

整数除法比整数乘法更慢,约30个机器周期。
向下舍入: 对于任意实数a,定义 ⌊ a ⌋ \lfloor a \rfloor a为唯一整数a’,使得 a ′ ≤ a < a ′ + 1 a' ≤ a < a' + 1 aa<a+1
⌊ 3.14 ⌋ = 3 \lfloor 3.14 \rfloor=3 3.14=3 ⌊ − 3.14 ⌋ = − 4 \lfloor -3.14 \rfloor=-4 3.14=4

向上舍入: 对于任意实数a,定义 ⌈ a ⌉ \lceil a \rceil a为唯一整数a’,使得 a ′ − 1 ≤ a < a ′ a'-1 ≤ a < a' a1a<a
⌈ 3.14 ⌉ = 4 \lceil 3.14 \rceil = 4 3.14=4 ⌈ − 3.14 ⌉ = − 3 \lceil -3.14 \rceil = -3 3.14=3

向上舍入与向下舍入的关系: ⌈ x / y ⌉ = ⌊ ( x + y − 1 ) / y ⌋ \lceil x/y \rceil=\lfloor (x+y-1)/y \rfloor x/y=(x+y1)/y
证明:令 x = q y + r x=qy+r x=qy+r,其中 0 ≤ r < y 0\leq r < y 0r<y,则 ⌊ ( x + y − 1 ) / y ⌋ = q + ⌊ ( r + y − 1 ) / y ⌋ \lfloor (x+y-1)/y \rfloor=q+\lfloor (r+y-1)/y \rfloor (x+y1)/y=q+(r+y1)/y。当 r = 0 r=0 r=0时, ⌈ x / y ⌉ = q \lceil x/y \rceil=q x/y=q;当 r > 1 r>1 r>1时, ⌈ x / y ⌉ = q + 1 \lceil x/y \rceil=q+1 x/y=q+1。因此,实现了向上舍入。

除以2的幂除法(右移)

无符号除法(向下舍入): 对于无符号数 x w x_w xw k k k,且 0 ≤ k < w 0 \leq k < w 0k<w,则逻辑移位 x > > k = ⌊ x / 2 k ⌋ x >> k = \lfloor x/2^k\rfloor x>>k=x/2k
证明:
x = [ x w − 1 , x w − 2 , ⋯   , x 0 ] x=[x_{w-1},x_{w-2},\cdots,x_0] x=[xw1,xw2,,x0] x ′ = [ x w − 1 , x w − 2 , ⋯   , x k ] x'=[x_{w-1},x_{w-2},\cdots,x_k] x=[xw1,xw2,,xk] x ′ ′ = [ x k − 1 , x k − 2 , ⋯   , x 0 ] x''=[x_{k-1},x_{k-2},\cdots,x_0] x=[xk1,xk2,,x0],其中 x x x x ′ x' x x ′ ′ x'' x均为无符号数。
x = 2 k x ′ + x ′ ′ x=2^kx'+x'' x=2kx+x 0 ≤ x ′ ′ < 2 k 0 \leq x'' < 2^k 0x<2k,得 x > > k = ⌊ x / 2 k ⌋ = x ′ x>>k= \lfloor x/2^k\rfloor=x' x>>k=x/2k=x

补码除法(向下舍入): 对于补码 x w x_w xw和无符号数 k k k,且 0 ≤ k < w 0 \leq k < w 0k<w,则算术移位 x > > k = ⌊ x / 2 k ⌋ x >> k = \lfloor x/2^k\rfloor x>>k=x/2k
证明:
x = [ x w − 1 , x w − 2 , ⋯   , x 0 ] x=[x_{w-1},x_{w-2},\cdots,x_0] x=[xw1,xw2,,x0] x ′ = [ x w − 1 , x w − 2 , ⋯   , x k ] x'=[x_{w-1},x_{w-2},\cdots,x_k] x=[xw1,xw2,,xk] x ′ ′ = [ x k − 1 , x k − 2 , ⋯   , x 0 ] x''=[x_{k-1},x_{k-2},\cdots,x_0] x=[xk1,xk2,,x0],其中 x x x x ′ x' x为补码数, x ′ ′ x'' x为无符号数。
则与无符号数类似,有 x = 2 k x ′ + x ′ ′ x=2^kx'+x'' x=2kx+x 0 ≤ x ′ ′ < 2 k 0 \leq x'' < 2^k 0x<2k,得 x > > k = ⌊ x / 2 k ⌋ = x ′ x>>k= \lfloor x/2^k\rfloor=x' x>>k=x/2k=x

补码除法(向上舍入): 对于补码 x w x_w xw和无符号数 k k k,且 0 ≤ k < w 0 \leq k < w 0k<w,则算术移位 ( x + ( 1 < < k ) − 1 ) > > k = ⌈ x / 2 k ⌉ (x +(1<<k)-1)>> k = \lceil x/2^k\rceil (x+(1<<k)1)>>k=x/2k
证明:
⌈ x / y ⌉ = ⌊ ( x + y − 1 ) / y ⌋ \lceil x/y \rceil=\lfloor (x+y-1)/y \rfloor x/y=(x+y1)/y,令 y = 2 k y=2^k y=2k,得 ⌊ ( x + 2 k − 1 ) / 2 k ⌋ = ⌈ x / 2 k ⌉ \lfloor (x+2^k-1)/2^k \rfloor=\lceil x/2^k\rceil (x+2k1)/2k=x/2k
( x + ( 1 < < k ) − 1 ) > > k = ⌈ x / 2 k ⌉ (x +(1<<k)-1)>> k = \lceil x/2^k\rceil (x+(1<<k)1)>>k=x/2k


2.4 浮点数

IEEE浮点表示

V = ( − 1 ) s × M × 2 E V=(-1)^s \times M \times 2^E V=(1)s×M×2E

符号s决定正负数;尾数M是二进制小数,范围是 1 ∼ 2 − ϵ 1 \sim 2- \epsilon 12ϵ 1 ∼ 1 − ϵ 1 \sim 1 - \epsilon 11ϵ阶码E用于对浮点数加权。

对于单精度32位浮点数,符号s占1位、阶码占k=8位、尾码占n=23位。
8位阶码字段 e x p = e 7 ⋯ e 0 exp=e_7 \cdots e_0 exp=e7e0编码阶码 E E E,23位小数字段 f r a c = f 22 ⋯ f 0 frac=f_{22} \cdots f_0 frac=f22f0编码尾数M。

深入理解计算机系统:第1-2章_第2张图片
图2 单精度浮点数IEEE标准格式

根据阶码域exp的不同,可分为下列情况:

  • 非规格化(阶码全0)
    阶码 E = 1 − ( 2 k − 1 − 1 ) = − 2 k − 1 + 2 E=1- (2^{k-1}-1)=-2^{k-1}+2 E=1(2k11)=2k1+2,尾数 M = f M=f M=f,用来表示0以及靠近0的数。
    最小非规格数尾码 M = 2 − n M=2^{-n} M=2n V = 2 − n − 2 k − 1 + 2 V=2^{-n-2^{k-1}+2} V=2n2k1+2
    最大非规格数尾码 M = 1 − 2 − n M=1-2^{-n} M=12n V = ( 1 − 2 − n ) × 2 − 2 k − 1 + 2 V=(1-2^{-n}) \times 2^{-2^{k-1}+2} V=(12n)×22k1+2

  • 规格化值(阶码非全0或非全1)
    阶码 E = e x p − ( 2 k − 1 − 1 ) E=exp-(2^{k-1}-1) E=exp(2k11),尾数 M = 1 + f M=1+f M=1+f,其中尾数加1用于获得额外精度。
    最小规格化数阶码 E = − 2 k − 1 + 2 E=-2^{k-1}+2 E=2k1+2 、尾码 M = 1 M=1 M=1,值 V = 2 − 2 k − 1 + 2 V=2^{-2^{k-1} + 2} V=22k1+2
    最大规格化数阶码 E = 2 k − 1 − 1 E=2^{k-1}-1 E=2k11、尾码 M = 2 − 2 − n M=2-2^{-n} M=22n,值 V = ( 1 − 2 − n − 1 ) × 2 2 k − 1 V=(1-2^{-n-1}) \times 2^{2^{k-1}} V=(12n1)×22k1

  • 特殊值(阶码全1)
    尾数域全0时,无穷大;尾数域非0时,NaN(Not a Number)。

深入理解计算机系统:第1-2章_第3张图片
图3 8位浮点数非负值示例(k=4, n=3)

非规格化数分布在0附近,浮点数并非均匀分布,约靠近原点处约稠密。

整数 12345 12345 12345转为单精度浮点数,二进制数为【11 0000 0011 1001】,小数表示为 1.1000000111001 × 2 13 1.1 0000 0011 1001 \times 2^{13} 1.1000000111001×213,因此存储为:

  • 符号域(1位),【0】;
  • 尾码域(23位)丢弃开头的1,并在后面补10个0,【100 0000 1110 0100 0000 0000】;
  • 阶码域(8位)为13加上偏置127,【1000 1100】;

你可能感兴趣的:(计算机系统)