Chapter1
基本思想
信息 是一系列的 位(bit) 和这些数据的 上下文(context) 。上下文决定了如何解码这些信息。例如,一串0和1的字符串,根据上下文可以解码为 整型 、浮点数 或 ASCII码。
一个程序是如何转化为目标文件的
Overview: 编译器驱动程序(如GCC)将 源程序文件 (hello.c) 翻译 成一个 可执行目标文件 (hello)。
四个阶段:
- 预处理阶段——根据 以#开头的语句 修改原始程序,生成一个 .i 文件。
- 编译阶段——编译器 将 hello.i 翻译成文本 hello.s 。这是用汇编语言写成的。
- 汇编阶段—— 汇编器 将
hello.s
翻译成 机器语言指令, 把这些指令打包 成 可重定位目标程序 ,保存在hello.o
中。 - 链接阶段—— 链接器将调用了的函数(如
printf
)相关的目标文件(已被单独预编好)链接到hello.o
文件中。得到hello
文件,这是一个可以被加载到 内存 中的可执行目标文件。
一个程序是如何执行的
以hello
为例。
1.外壳程序将输入的字符./hello
,外壳将字符读入 寄存器, 再放到存储器中。
2. 当输入回车表示结束输入时,外壳执行指令,将hello文件的代码和数据从磁盘复制到主存。
3. 处理器开始执行hello程序的机器语言指令。
4. “hello world“字符串的移动: 主存->寄存器->显示设备
进程
并发运行
指一个进程的指令和另一个进程的指令是交错执行的。
一个CPU看上去像是在并发地执行进程,实际上是处理器在进程间切换,这种机制叫做上下文切换。
上下文
跟踪进程运行所需的所有状态信息
虚拟存储器
它为每个进程提供了一个假象:每个进程都在独占地使用主存;每个进程看到的是一致的存储器,称为虚拟地址空间。
对于每个空间,从下往上的分区是:
程序代码和数据;
堆(malloc和free控制堆的膨胀和收缩)
共享库(C标准库)
栈(编译器用来实现函数调用,在程序执行期间可以动态变化大小)
内核虚拟存储器(不允许程序读写)
Chapter2 信息的表示和处理
存储器的概念
机器级程序将存储器视为一个非常大的字节数组(array of bytes),称为虚拟存储器(virtual memory)。存储器的每个字节都由一个唯一的地址来表示。所有虚拟地址空间(virtual address space)是所有的地址的集合。
字节
大多数计算机都是用8个位的Block,又称为字节,作为最小的可寻址的存储器单位。
字长
字长决定了虚拟地址空间的最大大小。一个字长为w位的机器拥有的地址为0~2^w-1,相当于一个大小为2^w的地址空间。
现在大多数计算机的字长是32位,因而内存的大小是4GB,约4*10^9个字节。
端的规则
跨越多字节的程序对象被存储在连续的地址空间,对象的地址为这串字节序列使用的最小的地址。
对于0x123456:
地址 | 0x01 | 0x02 | 0x03 |
---|---|---|---|
大端 | 12 | 34 | 56 |
小端 | 56 | 34 | 12 |
位运算
用XOR编写交换值的函数
a = a^b;
b = a^b;
a = a^b;
// 位运算性质: a^a=0;a^0=a
掩码
对某些位进行特定处理。
~0:一串超长的1,machine independent。对比:Machine dependent:0xFFFFFF…FFFF。
移位运算
右移的特殊情况
算术右移:在左端补原本最高有效位的值
逻辑右移:只补0
运算
判断无符号加法x+y是否溢出:
s = x+y, 若s