# 解读《深入理解计算机系统(CSAPP)》第3章程序的机器级表示
本章中,我们了解C语言机器级编程,通过让编译器产生机器级程序的汇编代码表示,了解了编译器和他的优化能力,以及机器、数据类型和指令集。
一、程序编码
gcc命令:C编译器 ;gcc -0g 代表机器代码的优化等级 机器级编程,两种抽象:一、由指令集体系结构或指令集架构来定义机器级程序的格式和行为,它定义了处理器状态、指令的格式、以及每条指令对状态的影响。二、机器级程序使用的内存地址是虚拟地址,提供的内存模型看上去是一个很大的、按字节寻址的数组。
二、数据格式
x86-64指令集包括完整的针对字节、字和双字的指令。
C声明 | Intel数据类型 | 汇编代码后缀 | 大小(字节) |
---|---|---|---|
char | 字节 | b | 1 |
short | 字(短整型) | w | 2 |
int | 双字(整型) | l | 4 |
long | 四字(长整型) | q | 8 |
char* | 四字 | q | 8 |
float | 单精度 | s | 4 |
double | 双精度 | l | 8 |
三、访问信息
一个x86-64的中央处理器单元(CPU)包含一组16个存储64位值的通用目的寄存器。这些寄存器用来存储整数数据和指针。
指令可以对这16个寄存器的低位字节中存放的不同大小的数据进行操作。生成1字节和2字节数字的指令会保持剩下的字节不变, 生成4字节数字的指令会把高位4个字节置为0(高16位)。
四、汇编指令
指令 | 效果 | 描述 |
---|---|---|
数据传输指令 | ||
mov | 传送 | |
pushq | 压入栈 | |
popq | 弹出栈 | |
leaq | 加载有效地址 | 是movq指令的变形 |
算术和逻辑操作 | ||
INC | 加1 | |
DEG | 减1 | |
NEG | 去负 | |
NOT | 取补 | |
ADD | 加 | |
SUB | 减 | |
IMUL | 乘 | |
XOR | 异或 | |
OR | 或 | |
AND | 与 | |
SAL | 左移 | |
SHL | 左移 | |
SAR | 算术右移 | |
SHR | 逻辑右移 | |
imulp | 有符号乘法 | |
mulp | 无符号乘法 | |
cqto | 转换为8字节 | |
idivq | 有符号除法 | |
divq | 无符号除法 | |
控制 | ||
CMP | 不修改寄存器的值,只设置条件码 | 比较 |
TEST | 测试 | |
SET | 根据条件码组合set0/1 | 访问条件码 |
jump | 跳转到另一条带标号的目的地 | 跳转指令 |
cmove | 用条件传送来实现条件分支 | |
switch_eg | 引用跳转表 | switch语句 |
过程 | ||
call | 控制从函数P转移到函数Q的过程 | 转移控制 |
%rdi %edx…… | 寄存器中的局部存储变量 | 数据传送 |
五、理解指针
1、每个指针都有都有一个值
2、指针用 & 创建
3、* 用于间接引用指针
4、数组引用(a[3])与指针运算和间接引用(*(a+3))有一样的效果
5、将指针从一种类型强制转换成另一种类型,只改变他的类型,不改变他的值
7、指针可以指向函数(int fun(int i); int (*
fp)(int i); fp = fun;)
六、小结
我们了解C语言机器级编程,通过让编译器产生机器级程序的汇编代码表示,了解了编译器和他的优化能力,以及机器、数据类型和指令集。
Java的目标代码是特殊的二进制——java字节码,可以看成是虚拟机的机器级程序,软件解释器处理字节代码。另外有一种及时编译(just-in-time compilation JIT)动态的将字节码序列翻译成机器指令。