本文对《深入理解计算机系统》(第三版)中第三章——“程序的机器级表示”中的部分内容进行了整理,以方便日后查阅。
目录
1. 整数寄存器
一个x86-64的中央处理单元(CPU)包含一组16个存储64位值得通用目的寄存器。这些寄存器用来存储整数数据和指针。
![](https://i-blog.csdnimg.cn/blog_migrate/a80aeee5e38ae843f6928a7d7226294f.png)
2. 操作数
大多数指令有一个或多个操作数(operand),指示出执行一个操作中要使用的源数据值,以及放置结果的目的位置。
操作数可分为三种类型:
(1) 立即数(immediate) 用来表示常数值。用$Imm表示立即数寻址,Imm表示一个整数。eg. $0x1F
(2) 寄存器(register) 表示某个寄存器的内容。用ra表示寄存器寻址,ra表示任意寄存器
(3) 内存引用 根据计算出的地址(通常称为有效地址)访问某个内存位置。常用寻址模式为Imm(ra, ri, s),其中ra, ri, s分别 表示基址寄存器、变址寄存器和比例因子。s必须是1、2、4或者8。ra, ri必须是64位寄存器。有效地址的计算公式为: Imm + R[ra] + R[ri]*s
3. 数据传送指令——MOV类。
将数据从源位置复制到目的位置。movabsq指令能够以任意64位立即数值作为源操作数,并且只能以寄存器作为目的。
![](https://i-blog.csdnimg.cn/blog_migrate/964fb86aeb25a8a124ba9cca1cb07e55.png)
4. 压入和弹出栈数据——PUSH操作和POP操作
![](https://i-blog.csdnimg.cn/blog_migrate/3272363c1c5ab74720ca779f94829ad5.png)
5. 算术和逻辑操作
![](https://i-blog.csdnimg.cn/blog_migrate/83f305ea5aa7d98ad488009439e20efa.png)
6. 条件码
CPU维护了一组单个位的条件码(condition code)寄存器,它们描述了最近的算术或逻辑操作的属性。可以检测这些寄存器来执行条件分支指令。
条件码通常不会直接读取,有三种常见的使用方法:
(1) 根据条件码的某种组合,将一个字节设置为0或者1
(2) 条件跳转到程序的某个其他的部分
(3) 可以有条件的传送数据
7. 比较和测试指令——CMP和TEST
CMP指令根据两个操作数之差来设置条件码。TEST指令根据两个操作数相与后的结果来设置条件码。这两个指令都不修改任何寄存器的值,只设置条件码。
![](https://i-blog.csdnimg.cn/blog_migrate/0ab00ceb2c304f3969be979fff020416.png)
8. SET指令
SET指令根据条件码的某种组合,将低位单字节寄存器元素或者一个字节的内存位置设置成0或者1。SET指令对应于条件码的第一种使用方法。
![](https://i-blog.csdnimg.cn/blog_migrate/258f42036a8b9eea0d43fbff5fdd4e07.png)
注意:
(1)SET指令后的后缀表示不同的条件,而不是操作数大小。比如setl、setb中 l 表示 less,b 表示 below。
(2)SET指令将低位单字节寄存器元素或者一个字节的内存位置设置成0或者1。为了得到一个32位或64位结果,必须对高位 清零。
9. JMP跳转指令
jmp指令让程序切换到一个全新的位置执行。通常用一个标号(label)来表示跳转的目的地。
jmp指令是无条件指令,分为直接跳转和间接跳转两种。直接跳转是给出一个标号作为跳转目标,该跳转目标是作为指令的 一 部分编码的,如jmp .L1。间接跳转的跳转目标是从寄存器或内存位置中读出的,写法是*后面跟一个操作数指示符,如 jmp *(%rax),这条指令表示从%rax中的值作为读地址,从内存中读出跳转目标。
![](https://i-blog.csdnimg.cn/blog_migrate/9437d304939bd6a43693632c2d8d7135.png)