3.2 程序编码
3.2 程序编码
linux> gcc -0g -o p p1.c p2.c
gcc:指GCC C编译器
-0g:告诉编译器使用会生成符合原始C代码整体结构的机器代码的优化等级。
执行流程:
-
C预处理器扩展源码,插入所有用#include命令指定的文件,扩展#define声明指定的宏。
-
编译器产生源文件的汇编代码(.s文件)
-
汇编器将汇编代码转化为二进制目标代码文件(.o文件)
目标代码是机器代码的一种形式,它包含所有指令的二进制表示,但未填入全局值的地址。
-
链接器将目标代码文件与实现库函数的代码合并,并产生最终的可执行代码文件(有命令行指示符-o p指定)。
3.2.1 机器级代码
机器级编程的两种抽象:
- 指令集体系结构或指令集架构(ISA),例如x86-64指令集,将程序的行为描述为按指令顺序执行。
- 机器级程序使用的内存地址是虚拟地址,提供的内存模型看上去是一个非常大的字节数组。
x86-64隐藏处理器状态
- 程序计数器:称为PC,在x86-64中表示%rip,给出将要执行的下一条指令在内存中的地址。
- 整数寄存器:包含16个命名位置,分别存储64位值,可以存储地址或整数数据。
- 条件码寄存器:保存算术或逻辑指令的状态信息
- 一组向量寄存器:存一个或多个整数或浮点数值。
程序代码的内存组成部分
- 可执行代码
- 系统需要的信息
- 用来管理过程调用和返回的运行时栈
- 用户分配的内存块(malloc)
3.2.2 代码示例
机器代码与对应的反汇编器特性:
- x86-64的指令长度从1到15个字节不等。
- 设计指令格式的方式是,从某个位置开始,可将字节唯一地解码成机器指令。
- 反汇编器只是将基于机器代码文件中的字节序列来确定汇编代码。