寄存器(Register)
寄存器是 CPU 内部的高速存储单元,是汇编编程中最核心的操作对象。8086 CPU 有 14 个 16 位寄存器,按功能分为几组。
核心思想
CPU 操作数据要么直接用立即数,要么从寄存器取,要么从内存取。寄存器最快,但数量有限(只有14个)。 相关内容详见 02-内存寻址。
通用寄存器(4个)
AX、BX、CX、DX 这四个寄存器用于存放一般性数据,每个都可以拆成两个独立的 8 位寄存器使用:
| 16位 | 高8位 | 低8位 | 特殊用途 |
|---|---|---|---|
| AX | AH | AL | 累加器,乘除法默认使用 |
| BX | BH | BL | 基址寄存器,常用于内存寻址 |
| CX | CH | CL | 计数器,[[07-转移指令与循环 |
| DX | DH | DL | 数据寄存器,乘除法和 [[10-中断与端口 |
mov ax, 1234H ; AX = 1234H
mov al, 56H ; AL = 56H(AX 变成 1256H)
mov ah, 78H ; AH = 78H(AX 变成 7856H)
易错点
只有 AX/BX/CX/DX 这四个可以拆成 8 位寄存器使用,其他寄存器(如 SI、DI、BP、SP)不能拆。
段寄存器(4个)
8086 CPU 有 20 位地址总线(可寻址 1MB 内存),但寄存器只有 16 位,所以采用段地址:偏移地址的方式寻址。
物理地址 = 段地址 × 16 + 偏移地址(即段地址左移4位 + 偏移)
| 段寄存器 | 名称 | 默认搭配 | 作用 |
|---|---|---|---|
| CS | Code Segment | IP | 指向当前执行的代码段 |
| DS | Data Segment | BX/SI/DI/[idata] | 指向数据段 |
| SS | Stack Segment | SP/BP | 指向栈段(详见 06-栈) |
| ES | Extra Segment | 需显式指定 | 附加段,用于串操作等 |
关键理解
内存里存的内容到底是”指令”还是”数据”,不取决于内存本身,而取决于哪个段寄存器指向它:
- CS:IP 指向的内存 → 被当作指令执行
- DS 指向的内存 → 被当作数据读取
- SS:SP 指向的内存 → 被当作栈操作 同一块内存,用不同方式解读,结果完全不同。
控制寄存器
| 寄存器 | 全称 | 作用 |
|---|---|---|
| IP | Instruction Pointer | 存放下一条指令的偏移地址,和 CS 配合(CS:IP 指向下一条指令) |
| SP | Stack Pointer | 栈顶指针,和 SS 配合(详见 06-栈) |
| FLAGS | 标志寄存器 | 存储 CPU 状态标志(详见 09-标志寄存器) |
不能直接赋值的寄存器
变址寄存器
| 寄存器 | 名称 | 用途 |
|---|---|---|
| SI | Source Index | 源变址寄存器,常用于串操作的源地址 |
| DI | Destination Index | 目的变址寄存器,常用于串操作的目的地址 |
| BP | Base Pointer | 基址指针,默认段寄存器是 SS(而非 DS),常用于访问栈中的参数 |
可以用于
[...]内存寻址的寄存器在 8086 中,只有 BX、BP、SI、DI 这四个寄存器可以放在方括号中进行内存寻址。 AX/CX/DX 不能直接用于
[ax]这种写法。
8位数据送入16位寄存器的正确方式
当需要把一个 8 位数据(字节)送入 16 位寄存器参与运算时,不能直接 mov dx, [0](这会读一个字而不是字节),正确做法:
mov dx, 0 ; 先将 16 位寄存器清零
mov al, ds:[0] ; 用低 8 位 AL 读入 8 位数据
mov ah, 0 ; 高 8 位 AH 清零
add dx, ax ; 现在 AX 中是正确的 16 位值(高位为0)
汇编语法基础
- 注释用分号
;(不是 C 语言的//) - 数值不加后缀默认是十进制
- 加
H后缀是十六进制:1000H、0ABCH - 加
B后缀是二进制:00010000B - 以字母(A-F)开头的十六进制数,前面必须加
0:0ABCH而不是ABCH - 字符串用单引号:
'a'、'abc'