《深入理解计算机系统(第三版)》第二章 信息的表示和处理
??计算机本身是由处理器和存储器子通过系统组成。在核心部分,我们需要方法来表示基本数据类型,比如整数和实数运算的近似值。然后,我们考虑机器级指令如何操作这样的数据,以及编译器又如何将C程序翻译成这样的指令。接下来,研究几种实现处理器的方法,帮助我们更好的了解硬件资源如何被用来执行指令。理解了编译器和机器级代码,我们就能了解如何通过编写C程序以及编译它们来最大化程序的性能。本章主要使我了解了如何表示和执行应用程序,通过一些技巧,来写出安全、可靠且充分利用计算资源的程序。知识点比较琐碎,下面是我通过本章的学习得到的一些收获:
1、三种最重要的数字表示:
- 无符号:基于传统的二进制表示法,表示大于或者等于零的数字;
- 补码:表示有符号(可正可负)整数的最常见的方式;补码编码具有唯一性;无符号数编码也具有唯一性。
- 浮点数:表示实数的科学记数法的以2为基数的版本。
补码与无符号数间的转换如图:
2、信息存储:程序将存储器视为一个字节数组,叫做虚拟存储器,数组中每个字节都有一个数字来标识,这个数字就是地址,所有可能的地址的集合叫做虚拟地址空间。虚拟地址空间是给程序提供的概念性映像,实际的实现是将RAM、硬盘、特殊硬件和OS软件结合起来。 编译器和运行时系统通过各种机制来分配和管理程序不同部分的存储,比如程序数据、指令、控制信息等。
3、指针是C语言的一个重要特性,它也有两个方面:
- 值:表示某个对象的位置;
- 类型:表示那个位置上所存储对象的类型(比如整数或者浮点数)。
对于任何数据类型T,声明T p; 表明p是一个指针变量,指向一个类型为T的对象。例如, char p;就将一个指针声明为指向一个char类型的对象。
4、十六进制表示法: 使用数字‘0’~‘9’以及字符‘A’~‘F’来表示16个可能的值。以ox或0X开头的数字常量,字符不区分大小写。
5、寻址和字节顺序:占多个字节的对象,解析它需要确定两个方面:对象地址,字节在存储器中如何排列
一般情况下,对象地址使用字节序列的最小地址
字节顺序有两种规则:小端法和大端法。
- 小端法就是低地址(地址值越大)对应高位;
- 大端法就是高地址(地址值越小)对应高位。
如下所示,变量x地址为0x100,十六进制值为0x01234567,地址范围是0x100 - 0x103,,大端和小端表示法分别如下:
6、布尔代数:二进制值是计算机编码、存储和操作信息的核心,所以围绕数值0和1也称为布尔代数。
7、强制类型的转换:无论指针以前是什么类型,强制转换它指向一个数据类型为unsigned char的指针。其结果保持位值不变,只是改变了解释这些位的方式。 但是强制转换也有一些缺陷,比如函数getpeername的安全漏洞。它的问题就是由于数据类型的不匹配造成的:在一个地方,长度参数是有符号数;而另一个地方,它又是无符号数,这样的不匹配会造成缺陷,甚至会导致安全漏洞。
8、整数运算:有符号数的运算在底层实际上执行和无符号数完全相同的指令,不过有符号数可能正溢出,也可能负溢出,当a、b都小于0,但他们的和大于0时发生负溢出,当a、b都大于0,但和小于0时发生正溢出。
??溢出可能会带来意想不到的后果。比如XDR库中饭的安全漏洞,XDR库是一个广泛使用的、程序见共享数据结构的工具,造成这个安全漏洞的原因是程序会在毫无察觉的情况下产生乘法溢出,超出的字节超越已分配的缓冲区的界限,因而破坏了其他的数据结构,这会导致程序崩溃或者行为异常。
9、IEEE浮点数表示:IEEE标准中指定浮点运算行为方法的一个优势在于,它可以独立于任何具体的硬件或者软件实现。
使用(-1)^s * M * 2^E 的形式表示一个数:
- 符号(sign)s决定该数的正负
- 尾数(significant)M是一个二进制小数
- 阶码(exponent)E对浮点数加权,权重是2的E次幂(可能是负数次幂)
一个二进制数被划分成3个字段来表示上诉形式:
- 单独的符号位s,编码符号s
- k位的阶码字段exp,编码阶码E
- n位小数字段frac,编码尾数M,编码出的值依赖于阶码字段的值是否为0
二进制小数:二进制小数点像左移动一位相当于这个数被2除。例如101.11表示数5·3/4
10、使用整数运算满足结合律、交换律和分配律。必须非常小心的使用浮点计算,因为浮点运算只有有限的范围和精度,而且并不遵守普遍的算数属性,比如结合律。