程序的机器级表示(一)
程序编码 假设一个C程序,有两个文件p1.c和p2.c。我们用Unix命令行编译这些代码: linux> gcc -Og-o p p1.c p2.c 命令gcc就是GCC编译器,这是Linux默认的编译器。编译选项-Og告诉编译器使用会生成符合原始C代码整体结构的机器代码的优化等级,使用较高级别的优化产生的代码会严重变形,以至于产生的机器代码和初始源代码之间的关系难以理解。 实际上,gcc命令调用了一整套程序,将源代码转换为可执行代码。首先,C预处理器扩展源代码,插入所有用#include命令指定的文件,并扩展所有用#define声明指定的宏。其次,编译器产生两个源文件的汇编代码,名字分别为p1.s和p2.s。接下来,汇编器会将汇编代码转换为二进制目标代码文件p1.o和p2.o。目标代码是机器代码的一种形式,它包含所有指令的二进制表示,但是还没填入全局值的地址。最后,链接器将两个目标代码文件与实现函数(如printf)的代码合并,并产生最终的可执行文件p(由-o p指定的)。 机器级代码 对机器级编程来说,其中两种抽象尤为重要。第一种是由指令集体系结构或指令集架构(Instruction Set Architecture,ISA)来定义机器级程序的格式和行为,它定义了处理器状态、指令的格式,以及每条指令对状态的影响。大多数ISA,包括x86-64