第02章 程序结构和执行

Posted by allon li on 2017-02-22

第02章 程序结构和执行

Tags: 深入理解计算机系统

[TOC]


信息的存储

总线宽度一般就是一个字长,一个字长的位数,就决定着这个系统的寻址宽度。
字长为 nn 那么它的寻址宽度为:00 ~ (2n1)(2^n - 1) 程序最多访问2n2^n个字节。

little endian(小端)目前android和ios都采用的是little endian。linux和windows也一样。
big endian(大端) java是继承了SUN的系统规则属于小端。所以在java网络传输时尤其注意。
image_1benbhdpfh541jgr13s3fs1qs39.png-172.3kB

C、C++都支持无符号类型,java仅支持有符号。

整数的表示

image_1bep6k353hh3apb1a1j12hn1oilm.png-271.8kB

无符号编码

全是正的,所以表示的正数值域很宽。

B2U4([1111])=123+122+121+120=15B2U_4([1111]) = 1\cdot2^3+1\cdot2^2+1\cdot2^1+1\cdot2^0 = 15

有符号补码 - 常用

最高位为负数,表示的值域:241-2^{4-1} ~ 24112^{4-1} -1,由此可以看出,因为0是非负数,所以多占了一个。有符号的位不是对称的。负数比正位大1。负数最小值在正方向上没有与之对应的数。

B2T4([1111])=123+122+121+120=1B2T_4([1111]) = -1\cdot2^3+1\cdot2^2+1\cdot2^1+1\cdot2^0 = -1

有符号反码

和补码一样,只是最高位多减个1 :2411-2^{4-1} -1
###有符号原码
最高位是-1: 1i=1nx2n-1\cdot\sum_{i=1}^nx\cdot2^n

有无符号转换

image_1bepe8di71l3kvjgbkjlvii9p9.png-190kB

整数类型转换

如果称位数少的为“小”,位数多的为“大”
\to 大 :零扩展
\to 小 :截断

整数的运算

判断加法溢出。用最大或者最小值跟目标值求差,再用差和另一个加数比较。如果那个加数比这个差大。就溢出。
image_1bepg9fg81sp6ceh1k5j1b4t16adm.png-599.8kB

浮点数

image_1beqdtlenf5q74h1v8214951gc013.png-126.1kB

  • 定点表示:约定机器中所有数据的小数点位置是固定不变的。由于约定在固定的位置,小数点就不再使用记号“.”来表示。通常将数据表示成纯小数或纯整数。定点数的表示方法就是整数是$\sum_{i=1}^n 2^i $ ,小数就是2的负幂次。这种的缺点是表达的数据很窄。
  • 浮点表示 - IEEE 754标准:浮点指小数点不是固定的,任意十进制数可以表示为:$$N = M \cdot10^E$$
    比如:$$234.56 = 2.3456*10^2$$
    只保留一位整数这种方式叫规格化表示。
    EE(Exponent) 阶码,它控制着小数点在什么位置上。
    MM(Significand)尾数,也叫有效数。是核心数值。下图中的Fraction。
    image_1besrrtt31jj3i8b17c1jfkohd1g.png-13.9kB

这样就可以通过阶码E做为幂次来表示小数点在什么位置,以上情况在二进制上亦然:

$$V = (-1)^s \cdot M \cdot 2^E$$

为什么32位浮点数阶码要有偏移量 ?

阶码有正有负,为了方便计算,加上一个比较大的正数。把所有阶码转为正值。这使得两个浮点数的指数大小的比较更为容易,实际上可以按照字典序比较两个浮点表示的大小。

为什么偏移是127 ?

  1. 8位移码的取值范围为0255(0000000011111111),但在浮点数的阶码中,00000000与11111111被保留用作特殊情况,所以阶码可用范围只有1~254,总共有254个值。
  2. 8位有符号数取值范围为-128+127(1000000001111111),这里的二进制用补码表示,其中特别规定补码10000000没有原码,为-128的补码,总共有256个值。
  3. 如果采用偏置128,在表达+127时会产生上溢(移码11111111被保留),所以在阶码中偏置为(128-1),与此同时,在表达-127时会产生下溢(移码00000000被保留),所以阶码中去掉-127与-128,取值范围为-126~127,总共254个值。

浮点运算

编译器对于浮点型运算可以开启优化,而部分优化会丢失极小的精度。但是默认情况下编译器比较保守的不会主动进行指令优化。