第一章 概述
第二章 信息表示和处理
第三章 程序的机器级表示
历史
IA32:Intel在1985年提出的机器语言
英特尔处理器系列俗称x86
IA32的64位扩展:x86-64
程序编码
> gcc -Og -o p p1.c p2.c
的全过程:
- 扩展源代码,插入所有
#include
命令指定的文件,并扩展所有用#define
声明指定的宏 - 编译器产生两个源文件的汇编源码
p1.s
p2.s
- 汇编器将汇编代码转化呈二进制目标代码文件
p1.o
p2.o
- 链接器将两个目标代码文件与实现库函数的代码合并
x86-64机器代码中一些寄存器:
- 程序寄存器PC,在x86-64中用
%rip
表示 - 整数寄存器包含16个命名的位置,分别存储64位的值
- 条件寄存器保存算数或逻辑指令的状态信息
- 一组向量寄存器可以存放一个或多个整数或浮点数值
> gcc -Og -S mstore.c
可以产生一个汇编文件mstore.s
> gcc -Og -c mstore.c
可以产生二进制目标文件mstore.o
> objdump -d mstore.o
可以可以对产生的二进制目标文件进行反汇编
所有以
.
开头的行都是指导汇编器和链接器工作的伪指令
数据格式
访问信息
x86-64的16个整数寄存器:
x86-64的操作数格式:
MOV
类指令:
moveb
传送字节movew
传送字movel
传送双字moveq
传送四字moveabsq
传送绝对四字
示例:
pushq
& popq
算术和逻辑操作
leaq
一元
二元
移位
操作符
乘除法
操作符
控制
条件码
leaq
不会改变条件码
访问条件码
跳转指令
跳转指令的编码
绝对地址和相对地址
用条件控制来实现条件分支
—-分割线—-分割线—-分割线—-p141,等有兴趣再看这个汇编
过程
过程P
调用过程Q
,Q
执行后返回到P
,包含以下机制:
- 传递控制:进入
Q
时PC
必须指向Q
的起始地址,返回时pc
需要指向p
中调用Q
后面那条指令的地址 - 传递数据:
P
向Q
传递若干个参数,Q
向P
返回一个值 - 分配和释放内存:开始时
Q
需要位局部变量分配空间,返回前需要销毁
运行时栈
x86-64
的栈向低地址方向增长,而栈指针%rsp
指向栈顶元素。将指针减小一个适当的量可以为没有指定初始值的数据在栈上分配空间。类似地,可以通过增加栈指针来释放空间。
栈帧的概念:当x86-64
过程需要的存储空间超出寄存器能够存放的大小时,就会在栈上分配空间。这个部分称为过程的栈帧。下图为栈帧的通用结构。
通过寄存器,过程
P
可以传递最多6个整数值,如果Q
需要更多的参数,P
可以在调用Q
之前在自己的栈帧里存储好这些参数。事实上,很多函数根本不需要栈帧(所有局部变量都可以保存在寄存器中,而且该函数不会调用任何其他函数时)