目录
前言
我们平时所说的程序是指双击后直接运行起来的程序,这样得到程序叫做可执行程序(Executable program),在Windows环境下一般以.exe为后缀。可执行程序的内部是一系列计算机指令和数据的集合,它们都使二进制的,对于程序员来说仅通过肉眼难以识别这些二进制代码,然而对于可以进行编译和链接的CPU来说却是小菜一碟。那么编译链接究竟是什么呢?且听下文分析↓
一、程序环境
在ANSI C的任何一种实现中,存在两个不同的环境。
第1种是翻译环境,在这个环境中源代码被转换为可执行的机器指令。
第2种是执行环境,它用于实际执行代码
二、程序的编译与链接
翻译环境的简图:
组成一个程序的每个源文件通过编译过程分别转换成目标代码(object code)。
每个目标文件由链接器(linker)捆绑在一起,形成一个单一而完整的可执行程序。
链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索序员个人的程序库,将其需要的函数也链接到程序中。
编译本身又分为三个阶段:
预编译,编译,汇编
预编译
源码中的 # 修饰的语句代表预处理指令
编译过程的预处理阶段(预处理阶段进行的是一些文本操作)主要完成的事情:
#include所指向的头文件中的所有内容会被"复制粘贴"到#include语句所在的源文件中
#define定义的符号的替换
注释的删除注意:该阶段不进行语法检查
接下来观察一段在VSCODE编辑器里运行的代码,看一下它的预编译是什么样子的
下面是预编译后产生的文件
编译
编译阶段是将C语言代码翻译成汇编代码, 其过程有:
- 语法分析;
- 词法分析;
- 语义分析;
- 符号汇总。
下面是编译之后生成的文件
编译后生成的文件变成了汇编代码
汇编
生成一个MF.o文件—目标文件
1.把汇编代码翻译成二进制指令存放到目标文件
2.形成符号表—会将符号给个地址,形成符号表
下面为汇编之后生成的文件
三、 链接
链接的相关过程有:
1. 合并段表(这里不解释,需了解细读《程序员的自我修养》这本书,里面对整个编译链接部分都有很详细的讲解)
2. 符号表的合并和重定位。
简单参考一下符号表的流程图:
链接过程完成后如果符号表中的无效地址仍然无法得到确定,编译器就会报出链接错误,各标识符是否有定义会在链接阶段被检查
运行环境
程序执行的过程:
1. 程序必须载入内存中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。
2. 程序的执行便开始。接着便调用main函数。
3.开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。
4.终止程序。正常终止main函数;也有可能是意外终止。