汇编入门
汇编基础,入门必备
字(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 | - |
ARM汇编的操作数顺序跟Intel是一样的,这里就不详细展开了,具体可以直接看官方文档。
寻址方式
顾名思义,寻址方式就是CPU根据指令中给出的地址信息来寻找有效地址的方式,是确定本条指令的数据地址以及下一条要执行的指令地址的方法。寻址方式分为两类,即指令寻址方式和数据寻址方式。
0x1. 指令寻址方式:
指令地址在内存中是按顺序安排的,当执行一段程序时,通常是一条指令接着一条指令地顺序进行。也就是说,从内存中取出第一条指令,然后执行;接着从内存中再取出第二条指令,继续执行;依次类推。这种顺序执行的过程,称为顺序寻址方式。为此,必须使用程序计数器PC(ARM下叫PC,x86下叫IP)来计数指令的地址(Tip1)。
当程序转移执行的顺序时,指令的寻址就采取跳跃寻址方式。所谓跳跃,就是下条指令的地址不再由PC给出,而是由本条指令给出。跳跃后,按新的指令地址开始顺序执行。因此,PC的内容也必须改变,以便能及时跟踪新的指令地址。
Tip1: 当执行一条指令时,首先需要根据PC中存放的指令地址,将指令由内存取到指令寄存器中,与此同时,PC中的地址或自动加1或由转移指针给出下一条指令的地址。
0x2. 数据寻址方式:
数据寻址方式比较多,这里只列出几种常见的寻址方式,基本上都是汇编语言里经常用到的。
0x21. 立即寻址:
指令的地址字段给出的不是操作数的地址,而是操作数本身,由于不需要访问内存取数,所以指令执行时间很短(Note1)。例如:mov 0x123, %rax
{ % note warning % }
Note1: 立即数只能作为源操作数,而不能作为目的操作数。
{ % endnote % }
0x22. 直接寻址:
指令的地址字段给出的是操作数的内存地址。因为直接给出操作数的内存地址而不需要经过某种变换,所以称为直接寻址。
0x23. 间接寻址:
间接寻址是相对直接寻址而言的,在间接寻址的情况下,指令地址字段给出的地址,是个形式地址不是操作数的真正地址,或者说该地址单元中的内容才是操作数的有效地址。
0x24. 相对寻址:
相对寻址是把PC的内容加上指令格式中的形式地址D而形成操作数的有效地址。”相对”寻址,就是相对于当前的指令地址而言,好处是程序员无须用指令的绝对地址编程,因而所编程序可以放在内存的任何地方。
0x25. 基址寻址:
在基址寻址方式中将CPU中的基址寄存器的内容,加上变址寄存器的内容而形成操作数的有效地址。基址寻址的优点是可以扩大寻址能力。
0x26. 变址寻址:
把CPU中某个变址寄存器的内容与偏移量D相加来形成操作数有效地址。参见上表👆
0x27. 寄存器寻址:
操作数不放在内存中,而是把操作数本身的值放在CPU的通用寄存器中。
0x28. 寄存器间接寻址:
把操作数地址放在CPU的通用寄存器中,而操作数本身的值则放在内存中。
参考资料
https://www.dongxin.online/assembly/assemblybasic.html