程序的链接
程序的链接相当重要,是代码到最后可执行文件的最后一步。理解程序的链接非常重要,让我们开始吧。
理解程序的链接之前我们得弄清楚程序的链接之前发生了什么
在链接之前有三步预处理、编译和汇编
预处理
主要用于 C 语言编译器对各种预处理命令进行处理。比如
- 头文件的包含
- 宏定义的扩展
- 条件编译的选择(#ifdef)
举个栗子: ̄へ ̄
对 include 的预处理就是把 .h
里面的插进这个代码里面。
可以用 gcc -E main.c -o main.i
看预处理之后的文件
编译
简单来说就是把 main.i 里面的代码转换成汇编代码
gcc -S main.i -o main.s
也可以
gcc -S main.c -o main.s
汇编
汇编的功能就是把生成的汇编语言代码转换成机器语言代码。因为通常最终的可执行目标文件由多个不同模块的构成,所以在生成单个模块的机器语言目标文件的时候,不可能确定每条指令或每个数据的最终地址,因此,通常把汇编生成的机器语言目标代码称为可重定位的目标文件
啥是可重定位?
假如有两个文件如下:
// main.c
#include <stdio.h>
void add(int, int);
int main() {
add(10, 20);
return 0;
}
// func.c
void add(int x, int y) {
return x+y;
}
首先要记住的的是,在汇编过程中是对每一个文件单独进行。生成单个文件的可重定位的目标文件。
注意!是单个文件!
我们使用gcc -c main.s -o main.o
的时候很显然有一个 add()
函数只被声明没有被定义。不知道 add()
的内容。更不知道 add()
的地址。而在汇编代码中我们必须知道调用函数的地址。而在生成的可重定位目标文件中,总不能把调用函数的地址空着吧?需要填一个虚假地址,在链接以后,将多个可重定位目标文件合并在一起,才有可能知道 add()
的真正位置。
这就是重定位。你们懂了吗?
链接
其实链接就是可执行目标文件的生成
啥是可执行目标文件?
就是 CPU 可以直接放入内存了,可以执行了。没有那些虚假地址了。链接主要分为两步,我尽量把这两步说清楚,如果觉得不错,就给我点个喜欢吧。