第八章 从源文件到可执行文件
从这一章理解到的是,源代码是用某种编程语言编写的代码,源文件是保存源代码的文件,源代码经过编译后得到的是本地代码(本地代码用十六进制表示),本地代码的内容就是数值的罗列,而编译源代码还需要经过词法解析、语法解析、词义解析、中间代码生成、优化,最后得到目标代码。
源文件仅经过编译是无法得到可执行文件的,编译后得到的是目标文件,还需要进行“链接”处理,这就牵扯到链接器,链接器就是把多个目标文件结合,生成1个EXE文件的处理,就是链接运行连接的程序。由于编写的源代码中,包含自己编写的函数和内部函数,像自己编写的函数是存储在源文件在的,而内部函数就不在其源文件中,是存在扩展名为.lib的库文件中,库文件是指把多个目标文件集成保存在一个文件中的形式,链接器指定库文件后,就会从中把需要的目标文件抽取出来,并同其他目标文件结合起来生成EXE文件。
其生成EXE文件需要链接一个目标文件的启动,例c0w32.obj,这个目标文件中记述的是同所有程序起始位置相结合的处理内容,即程序的启动。标准函数是不通过源代码形式,而是通过库文件形式和链接器一起提供的函数,例如本章中的sprintf()。
Windows以函数的形式为应用提供了各种功能,这样形式的函数被称为API,API的目标文件不是存储在通常的库文件中,而是存储在名为dll文件的特殊库文件中。例如本章的MessageBox()是存储在import32.lib中,但实际上存储在user32.dll文件中,import32.lib中仅存储了两个信息,一是MessageBox()是在user32.dll这个DLL文件中,另一个是存着DLL文件的文件夹信息。像这样的库文件称为导入库。
EXE文件是单独存储在硬盘中的,作为本地代码的程序,其没有给变量及函数指定实际的内存地址,而是分配了虚拟的内存地址,在程序运行时,虚拟的内存地址就会转换为实际的内存地址,EXE文件会在EXE文件的开头追加转换内存地址所需的必要信息,这个信息成为再配置信息。
EXE文件的内容分为在配置信息、变量组、函数组,当程序加载到内存后,还会再生成两个组,那就是堆和栈。(其一部分用于操作系统)栈是用来存储函数内部临时使用的变量(局部变量)以及函数调用时所用的参数的内存区域,堆是用来存储程序运行时的任意数据及对象的内存领域。栈中对数据进行存储和舍弃的代码是由编译器自动生成的,而堆则需要根据程序员编写的程序来进行申请分配或释放。