目录
一、什么是编译
1、编译本质是将人类可读的程序源码转换为机器可以执行的机器指令。
2、将源程序转换为机器指令的工具叫做编译器,比如gcc,armcc,arm-linux-gcc等编译器。
二、编译详细流程
以C语言编译为例:编译流程大致分为以下几步:
1、预处理
预处理阶段会进行 宏替换,头文件展开,条件编译过滤,用户注释清除。
测试源码 mian.c,文件内容如下:
#include <stdio.h>//用于测试头文件包含
#define BIN_XYB_TEST (10)//用于测试宏替换
#if BIN_XYB_DEFINE //用于测试编译条件
#define BIN_XYB_STR "DEFINE STR"
#else
#define BIN_XYB_STR "NO DEFINE STR"
#endif
//test //用于测试注释清除
int main()
{
int i = BIN_XYB_TEST;
printf("hello world:%d!\r\n", i);
printf(BIN_XYB_STR);
return 0;
}
预处理main.c:gcc -E main.c -o main.i 。
生成预处理后的文件 main.i ,如下图:
对比源问件和目标文件结果如下:
2、编译
编译阶段会进行 检查语法错误,生成汇编文件。
编译阶段详细分为:词法分析,语法分析,语义分析,代码优化,目标代码生成。
编译main.i:gcc -S main.i -o main.s 。
生成汇编文件:main.s,如下图:
用户源码和生成汇编文件对比如下:
推荐一个网站,改工具可以将用户源码编译为汇编文件,支持多种编译器,方便用户深入理解C语言编译后的汇编源码,工具网址:Compiler Explorer
。
3、汇编
汇编阶段会将汇编文件转换为二进制文件。
编译main.s:gcc -c main.s -o main.o,结果如下图:
生成的main.o文件是二进制形式,以二进制打开,内容如下:
4、链接
链接阶段会将编译后的二进制文件中的函数调用(包括一些静态库的中接口的调用)赋予实际意义,将程序进行整体组装,生成最终可执行的文件。
链接命令:gcc main.o -o main
整个流程下来,生成最终可执行文件main,./main执行,看到有正常输出。
三、总结
编译过程是将人类可看懂的源码语言转变为计算机可执行的指令。
当前阶段,人类可识别的源码语言大致包括两种,一种是编译型语言(比如C语言,C++语言等),也就是本文介绍的,另一种是解释型语言,也就是平时所说的脚本语言(比如Python、Lua等)。
编译型语言在开发平台上,将人类可识别的源码转换为计算机指令(可以理解为程序包),将程序包下载到设备,设备直接执行。
解释型语言是将人类可识别的源码作为程序包添加到设备中,设备需要先将人类可识别的源码转换为机器指令,然后再执行机器指令,相当于是边解释边执行。
相比编译型语言,解释型语言速度较低,但是方便易用,可快速跨平台。