程序的编译链接【编译链接大概步骤】

😀 前言

🙂 翻译环境和执行环境

翻译环境:

在这个环境中源代码被转换为可执行的机器指令(二进制的指令)。

执行环境:

它用于实际执行代码。

在这里插入图片描述

我们日常使用的VS2019就是一个集成开发环境,结合了编辑、编译、链接、调试等多种功能,其中编译使用的是 cl.exe, 链接使用的是 link.exe 文件中,不同的编辑器使用的可能不同。

😶 编译和链接

  • 组成一个程序的每个源文件通过编译过程分别转换成目标代码(object code)。
  • 每个目标文件由链接器(linker)捆绑在一起,形成一个单一而完整的可执行程序。
  • 链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员个人 的程序库,将其需要的函数也链接到程序中。

在这里插入图片描述

其中编译又分为:预编译、编译、汇编 三步操作

为了方便演示,接下来使用Linux下的gcc进行实验。

实验代码:

// test.c
#include <stdio.h>

extern Add(int a, int b);

// 测试注释和#define
#define Max 100

int main()
{
	int z = Max;
	int a = 10;
	int b = 20;
	int c = Add(a, b);
	printf("%d\n", c);
	
	return 0;
}
// add.c
int Add(int a, int b)
{
	return a + b;
}

😵‍💫 预编译(预处理)

我们可以使用下面的指令将程序编译停留在预编译后:

gcc test.c -E -o test.i
gcc add.c -E -o add.i

打开test.i 可以发现多了很多行,同时注释的代码和 #define 都不见了:

在这里插入图片描述

再从/usr/include 这个路径下打开stdio.h 这个文件可以发现 test.i 中多出来的就是stdio.h的内容

在这里插入图片描述

那么就可以确定预编译阶段进行了一下几个操作:

  1. 头文件的包含 (#include
  2. #define 定义符号的替换
  3. 注释的删除

以上三个都是属于文本操作

😵‍💫 编译

将程序停留在编译之后:

gcc test.i -S -o test.s
gcc add.i -S -o add.s

打开test.s 可以看到:

在这里插入图片描述

这些都是之前在VS 中看到的反汇编。也就是说编译将C语言代码翻译成了汇编代码。其过程相当复杂,主要是做了一下几个操作:

  1. 语法分析
  2. 词法分析
  3. 语义分析
  4. 符号汇总

符号汇总:将文件中的全局符号汇总出来(局部的符号不管), 基本上就是函数名

😵‍💫 汇编

将程序停留在编译之后:

gcc test.s -c -o test.o
gcc add.s -c -o add.o

生成的就是目标文件。在Windows下目标文件的后缀时.obj,Linux下的后缀时.o

打开test.o

在这里插入图片描述

发现全是乱码,也就是说汇编将汇编指令翻译成了二进制的指令。

但是这时候在编译阶段进行的符号汇总就派上用场了,这些符号在汇编阶段被制成了符号表。二进制文件我们时看不懂的,在Linux下可执行程序的格式是:elf ,所以我们可以借助readelf 来查阅可执行文件:

readelf -s test.o

在这里插入图片描述

readelf -s add.o

在这里插入图片描述

汇编就是对每个编译阶段汇总的符号赋予地址(如果在文件中找不到该符号的有效内容,赋予无效地址),即:

在这里插入图片描述

😵‍💫 链接

链接阶段做的就是:

  1. 合并段表
  2. 符号表的合并和重定位

合并段表就是将每个目标文件的各个段整合起来,符号表的合并就是将各个目标文件的符号表合并成一个表,并检查每个符号的地址:

在这里插入图片描述

🌈 总结

程序的编译和链接过程是很复杂的,能力有限,只能学习这些大概的概念。

Linux 指令汇总:

// 编译的各个阶段:
ESc  ——> iso

// 查看目标文件:
readelf -[options] filename

// 头文件路径:
/usr/include
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_featherbrain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值