X86 汇编语言学习笔记
以 intel 上世纪推出的 8088/8086 处理器为切入点学习 X86 汇编语言
处理器与总线
X86 系列 CPU 的寄存器
在最初的 8086 系列 CPU 中仅有 14 个 16 位的寄存器,按功能可分为:8 个通用寄存器、4 个段寄存器和 2 个控制寄存器;通用寄存器又可以分为数据寄存器(AX, BX, CX, DX)、地址指针寄存器(BP, SP)、变址寄存器(SI, DI)
1985年,intel 推出了 80386 处理器,这是 x86 系列的第一款 32 位处理器,主寄存器被扩展到了 32-bit。所有 32 位主寄存器的命名方式就是在原先寄存器名基础上加了一个 E。后来随着 AMD 在 2003 年推出第一款 x86-64 架构的 64 位处理器,主寄存器又被扩展到了 64-bit,也是在原先的基础上把 E 改成了 R,即 Register(如上图所示)。
此外,x86-64 架构也新增了 R8 ~ R15 寄存器,如同先前已有的寄存器那样,也可以访问其低位,分别用 \(\mathrm{R}x\mathrm{B}\)、\(\mathrm{R}x\mathrm{W}\)、\(\mathrm{R}x\mathrm{D}\) 来表示(Byte, Word, Double-word)
寻址方式
flowchart LR;
a(寻址方式) --- ima(立即寻址) & bva(基址变址寻址) & ta(隐含寻址)
bva --- da(直接寻址) & ia(间接寻址)
ia --- ra(寄存器间接寻址) & ma(存储器间接寻址)
立即寻址
由指令直接给出运算的数据(操作数是立即数),为常数形式或字符形式:
1 |
|
基址变址寻址
方括号内表示偏移地址,由至多三个部分组成:基址寄存器内容 + 变址寄存器内容 + 位移量
只有一个常数就是直接寻址:
方括号里就是操作数的偏移地址,也就是被操作的数据在距某一段(默认为数据段)段首的偏移多少距离的内存单元里面
1
mov ax, [1200h] ; 操作的数据被存放在距 DS 1200 远的地方
如果要人为指定逻辑段,可以用段重设:
1
mov ax, es: [1200h] ; 操作的数据被存放在距 ES 1200 远的地方
只有一个寄存器名就是寄存器间接寻址:
需要注意的是,仅4个通用寄存器可用于存数据的偏移地址,即 BX, BP, SI, DI
1
mov ax, [bx] ; 把由 BX 存着的偏移地址上的内存单元数据送给 AX
寄存器名 + 一个常数就是寄存器相对寻址:
操作数的段地址(数据处于哪个段)取决于选择哪一个间址寄存器
- BX, SI, DI : 默认在数据段
- BP : 默认在堆栈段
两个寄存器就是基址变址寻址:
1
2
3mov al, [bx]5
mov al, [bx + 5] ; 和上个语句完全一样
mov ax, [bx][si] ; 相当于 BX + SI
隐含寻址
1 |
|
指令系统
数据传送指令
flowchart TB;
cat(数据传送类指令) --- gm(通用数据传送指令) & io(输入输出指令) & am(地址传送指令) & fm(标志传送指令)
通用数据传送指令
一般数据传送指令
格式: \[\operatorname{mov}\;dest,\,src\]
将 src 中的数据传送给 dest,作个不太恰当的比方就是 C++ 中的
1 |
|
但是需要注意几点:
- 两操作数字长必须相同
- 两操作数不允许同时为存储器操作数;
- 两操作数不允许同时为段寄存器;
- 在源操作数是立即数时,目标操作数不能是段寄存器;
- IP 和 CS 不作为目标操作数,FLAGS 一般也不作为操作数在指令中出现。
堆栈操作指令
格式: \[\operatorname{push}\;operand\qquad\operatorname{pop}\;operand\]
1 |
|
注意:
- 操作数可以是寄存器或存储器两单元,但不能是立即数
交换指令
格式: \[\operatorname{xchg}\;reg,\,mem/reg\]
1 |
|
查表转换指令
格式: \[\operatorname{xlat}\]
所做操作是用 BX 的内容代表表格首地址,AL 内容为表内位移量,BX + AL 得到要查找元素的偏移地址
字位扩展指令
此类指令将符号数的符号位扩展到高位
算术运算指令
加法
普通加法指令 ADD
格式: \[\operatorname{add}\;operand_1,\,operand_2\]
将 operand1 和 operand2 相加后,结果送入 operand1 中
1 |
|
带进位的加法指令 ADC
和 ADD 指令一样,只不过还加了 CF 标志位;ADC 指令多用于多字节数相加,使用前要先将 CF 清零
自增指令 INC
格式: \[\operatorname{inc}\;operand\]
1 |
|
To be continued...