CS110 计算机体系结构 5 C.A.L.L.

C.A.L.L,是编译 Compilation - 汇编 Assembly - 链接 Linking - 加载 Loading 的缩写,是从(编译执行类语言)程序代码到进程的一般过程。我们接下来一个个部分来看。
编译 Compilation
对于 C 语言而言,编译过程由 C 编译器(如 gcc)完成。在这个过程中,程序员把写好的代码文件 main.c 交给编译器,然后编译器负责把这份代码编译为汇编代码文件 main.s,其中存放的是汇编语言代码,如 RISC-V。
既然是负责把高级语言转换为汇编语言,编译器就需要恪尽职守地努力”优化“转换生成的汇编语言,使其执行需要的时空开销尽可能小。我们在使用 gcc 进行编译时,可以选择 -O2 -O3 这样的优化策略——这些策略就是不同激进程度的优化。优化有很多种类型,在此仅举一个例子来供读者理解:
1 | int sum(int n) { |
对于以上函数,如果按照
-O0的忠于源码的优化方式来编译,编译结束后的汇编代码可能是这样的(事实上,gcc 的翻译结果并不是 RISC-V,在此仅作演示,方便理解):
1 | sum: |
如果我们按照
-O3的激进的优化方式来编译,结果可能会变成类似于这样:
1 | sum: |
可以看到,最直观的区别就是,
-O3优化的汇编代码比-O0的汇编代码短得多。事实上,-O3优化在这里避免了不必要的内存存取,改在寄存器中更快地完成这部分工作;甚至,这种优化还将庞大的循环直接从数学上化简成了求和公式。-O3优化,在代码的时空复杂度上讲,比-O0优化有很大的缩减。
以上只是一个非常浅显的、便于理解的优化的例子。在后续的章节中,我们可能会涉及到如循环展开之类的优化方式,等涉及到时再补充。
汇编 Assembly
汇编过程是由汇编器 Assembler 完成的,它把由编译器生成的汇编代码汇编成二进制代码——这个过程的重点部分,我们已经在前两章中讨论过了,在此概括、补充一下完整过程:
第一步,根据含有伪指令的汇编代码来组织代码和数据,如将伪指令替换为标准指令、确定代码段、数据段的位置,声明全局符号等;第二步,汇编器将处理后的标准指令转换成二进制01串,生成机器语言;第三步,汇编器将生成的机器语言、信息表等打包为目标对象文件 .o,供后续链接器使用。
大端序 / 小端序
除了前面涉及的 RISC-V 代码翻译问题外,这里需要额外补充的是关于大端序/小端序的内容。所谓大端序/小端序 Big/Little Endian,就是缓冲区、内存、硬盘等存储容器中字节的存放/读取顺序。不难看出,这个顺序对于读取一段数据或代码来说至关重要。其中,小端序指的是最低位在最右侧的写法,大端序指的是最低位在最左侧的写法。RISC-V 使用的是小端序。比如,对于 0x12345678 这样一段十六进制数据,不同方式的存储如下:
| 内存地址 | 0x00 | 0x01 | 0x02 | 0x03 |
|---|---|---|---|---|
| 小端序 | 0x78 | 0x56 | 0x34 | 0x12 |
| 大端序 | 0x12 | 0x34 | 0x56 | 0x78 |
需要注意的是,具体按照小端序还是大端序存储/读取只是一种解释规则,具体顺序由 CPU 管理。另外,不论是小端序还是大端序,在每个字节内部的存储顺序是不会改变的——这是在说,即使是小端序,0x78 在同一内存地址字节上的存储方式还是 0b 0111 1000,而不会发生任何翻转。
汇编器的输出
这里简单整理一下汇编器的输出内容,主要包括代码和信息表两类,有兴趣的读者可以看一眼。
- 目标文件头 Object file header 包含目标文件中其它部分的大小和位置信息
- 文本段 Text segment 存储可执行的机器码
- 静态数据段 Static data segment 存储静态数据
- 符号表 Symbol table 列出文件中的标签和静态数据,方便被其他程序引用
- 重定向表 Relocation table 包含之后需要被链接器 Linker 修正的代码
- 调试信息 Debugging info 用于调试程序,记录变量名、函数名、行号与机器代码的对应关系
链接 Linking
【施工中】
- 标题: CS110 计算机体系结构 5 C.A.L.L.
- 作者: aaaaa
- 创建于 : 2026-08-13 22:00:00
- 更新于 : 2026-08-13 22:43:27
- 链接: https://redefine.ohevan.com/2026/08/13/零基础速通系列/CS110 计算机体系结构/零基础速通:CS110_计算机体系结构_5/
- 版权声明: 版权所有 © aaaaa,禁止转载。