源文件到执行文件的步骤是怎样的?

283 阅读4分钟

本地程序

使用各自编程语言写的程序叫做源代码,该文件叫做源文件,由于CPU只能直接执行本地代码的程序,所以源代码是不能直接运行的。那么源代码是怎么变成本地程序,被CPU执行的呢?需要哪些步骤呢?

.EXE文件

Windows采用.EXE文件当作本地文件,可以使用二进制或者十六进制查看一下内容,也可以说Dump一下文件。

image-20230312222532448

编译器

把高级语言编写的文件,使用编译器转换为本地代码。编译器首先要读入代码的内容,编译器内就如同有一个源代码和本地代码对应表一样,将这些源码转换成本地文件。

读入源代码还要经过语法解析、句法解析、语义解析等,才能生成本地代码。

image-20230312222912121

链接

编译器转换源代码后,就会生成本地文件,但是没办法直接运行,为了得到EXE文件,还需要链接操作。

很多语言自带的函数还没有引入,所以不能直接执行,需要很多包含相应函数的目标文件,这种把多个目标文件和编译后产生的文件结合,才能执行,这一步叫做链接,运行链接的程序叫做链接器

启动和库文件

启动是一个目标文件记录的所有程序起始位置结合处理的内容,而库文件指的是把多个目标文件集成保存到一个文件中的形式,当链接器指定到库文件后,就会从中把需要的目标文件抽取出来,同其他目标文件一起结合生成EXE文件。

有一些函数不是通过源代码的形式,而是通过库文件的形式和编译器一起提供的,这样的函数叫做标准函数。之所以使用库文件是因为这样避免链接器参数指定太多目标文件。

ilink32 -Tpe -c -x -aa c0w32. obj Sample1. obj, Sample1. exe,, import32. lib cw32. lib

DLL文件和导入库

Windows提供了很多函数,被称为API。这些API的目标文件,不是存储在库文件中,而是存储在DLL中。

  1. 导入库:有的库文件(.lib格式的)中只保存了某个函数是保存于某个DLL文件中这样的信息,这就叫做导入库
  2. 静态链接库:有的存储着目标文件的实体,这种就叫做静态链接库

image-20230312225024400

可执行文件运行时的必要条件

EXE文件会给变量及函数分配虚拟的内存地址,程序运行时,虚拟的内存地址会转换成实际的内存地址。链接器会在开头追加转换内存地址所需的必要信息,这个信息被称为再配置信息,也就是变量和函数的相对地址。

源码中,变量和函数在不同的位置上分散开,但是EXE文件在链接后,这些内容就会变成一个连续排列的组。通过记录变量和函数的相对地址,记录相对于基点地址的偏移量,变量的内存地址可以用相对于变量组起始位置这一基点的偏移量来记录,函数的内存地址也可以用相对于函数组起始位置的基点偏移量来记录,各个组的基点的内存地址在程序运行时被分配。

image-20230313080406332

程序加载时生成栈和堆

EXE文件的内容分为再配置信息、变量组和函数组,当程序加载到内存以后,还会生成两个组,栈和堆

栈:用来存储内部临时使用的变量(局部变量),以及函数调用时所用的参数的内存区域。

堆:用来存储程序运行时的任意数据及对象的内存领域。

EXE文件中不存在栈及堆的组,而是在EXE文件加载到内存后开始运行时得到分配栈和堆的内存空间。所以内存中的程序包含以下四个部分:用于变量的内存空间、用于函数的内存空间、用于栈的内存空间、用于堆的内存空间。

image-20230313081056955

栈的内存空间在进行存储和舍弃的代码,是由编译器来完成的,而堆在申请分配或者释放时,是由程序员来完成的。