汇编入门必备

字(word)

CPU可以处理两种尺寸的数据,即(word)和字节(byte),CPU和内存之间的数据传送单位通常是一个字长。

我们知道,1byte = 8bit,那么字长又是多少呢?其实字长通常跟CPU的位数相同。例如:64位CPU字长就是64位,即1word = 8byte,寄存器大小也是64位。但是也有个别情况,比如 Intel 80386CPU是32位的,但字长却是16位,即1word = 2byte,这是为了向后兼容80286CPU(16位)。

汇编语言分类

这里主要介绍最常见的两种CPU架构,即ARM架构和Intel架构。ARM架构主要用户移动设备,比如iOS和Android,而Intel架构主要用于台式电脑。每种CPU架构都有其对应的指令集,于是也就有了不同类型的汇编语言。

常见的汇编语言有两种:ARM汇编和x86汇编。而x86汇编按语法格式又分为Intel汇编AT&T汇编。Intel和AT&T语法区别见下表:

项目 Intel AT&T 说明
寄存器名 rax %rax AT&T要在寄存器前加%
操作数顺序 目标数在前mov rax, rdx 目标数在后mov %rdx, %rax 将rdx的值赋给rax
立即数 原样mov rax, 5 数字前加$mov $5, %rax 将5赋给rax
十六进制立即数 开头加0结尾加H,例如010H 开头加0x,例如0x10 十六进制数10
访问内存长度表示 开头加BYTE PTR, WORD PTR, DWORD PTR和QWORD PTR 结尾加b,w,l,q 分别表示字节,字,双字和四字
引用全局或静态变量var的值 [var] var -
引用全局或静态变量var的地址 var $var -
直接寻址/绝对寻址 [imm] imm imm表示立即数
间接寻址 [reg] (%reg) reg表示寄存器
基址相对寻址 [reg+imm] imm(%reg) -
变址寻址 [base+index] 或 imm[base+index] (base,index) 或 imm(base+index) base和index均为寄存器
比例变址寻址 imm[base+index*scale] imm(base, index, scale) scale只能是1, 2, 4, 8其中的一个数字 (1省略不写就是普通变址寻址)
代码注释 指令和注释用 ; 分开,例如:mov rax, rdx ;我是注释 同Intel汇编 -
所在平台 Windows Unix -

对于iOS开发来说,iOS真机上的汇编格式为ARM而模拟器上的格式则为AT&T,所以我们重点掌握下这两种汇编即可。ARM汇编的操作数顺序跟Intel是一样的,这里就不详细展开了,具体可以直接看官方文档

寻址方式

顾名思义,寻址方式就是CPU根据指令中给出的地址信息来寻找有效地址的方式,是确定本条指令的数据地址以及下一条要执行的指令地址的方法。寻址方式分为两类,即指令寻址方式数据寻址方式

0x1. 指令寻址方式:

指令地址在内存中是按顺序安排的,当执行一段程序时,通常是一条指令接着一条指令地顺序进行。也就是说,从内存中取出第一条指令,然后执行;接着从内存中再取出第二条指令,继续执行;依次类推。这种顺序执行的过程,称为顺序寻址方式。为此,必须使用程序计数器PC(ARM下叫PC,x86下叫IP)来计数指令的地址(Tip1)。

当程序转移执行的顺序时,指令的寻址就采取跳跃寻址方式。所谓跳跃,就是下条指令的地址不再由PC给出,而是由本条指令给出。跳跃后,按新的指令地址开始顺序执行。因此,PC的内容也必须改变,以便能及时跟踪新的指令地址。

Tip1: 当执行一条指令时,首先需要根据PC中存放的指令地址,将指令由内存取到指令寄存器中,与此同时,PC中的地址或自动加1或由转移指针给出下一条指令的地址。

0x2. 数据寻址方式:

数据寻址方式比较多,这里只列出几种常见的寻址方式,基本上都是汇编语言里经常用到的。

0x21. 立即寻址:

指令的地址字段给出的不是操作数的地址,而是操作数本身,由于不需要访问内存取数,所以指令执行时间很短(Note1)。例如:mov 0x123, %rax

Note1: 立即数只能作为源操作数,而不能作为目的操作数。

0x22. 直接寻址:

指令的地址字段给出的是操作数的内存地址。因为直接给出操作数的内存地址而不需要经过某种变换,所以称为直接寻址。

0x23. 间接寻址:

间接寻址是相对直接寻址而言的,在间接寻址的情况下,指令地址字段给出的地址,是个形式地址不是操作数的真正地址,或者说该地址单元中的内容才是操作数的有效地址。

0x24. 相对寻址:

相对寻址是把PC的内容加上指令格式中的形式地址D而形成操作数的有效地址。"相对"寻址,就是相对于当前的指令地址而言,好处是程序员无须用指令的绝对地址编程,因而所编程序可以放在内存的任何地方。

0x25. 基址寻址:

在基址寻址方式中将CPU中的基址寄存器的内容,加上变址寄存器的内容而形成操作数的有效地址。基址寻址的优点是可以扩大寻址能力。

0x26. 变址寻址:

把CPU中某个变址寄存器的内容与偏移量D相加来形成操作数有效地址。参见上表👆

0x27. 寄存器寻址:

操作数不放在内存中,而是把操作数本身的值放在CPU的通用寄存器中。

0x28. 寄存器间接寻址:

把操作数地址放在CPU的通用寄存器中,而操作数本身的值则放在内存中。


参考资料:

https://Intel 80386 Reference Programmer's Manual https://en.wikipedia.org/wiki/Assembly_language https://baike.baidu.com/item/%E5%AF%BB%E5%9D%80%E6%96%B9%E5%BC%8F

最后更新: 10/16/2019, 8:29:31 PM