寄存器(Register)

寄存器是 CPU 内部的高速存储单元,是汇编编程中最核心的操作对象。8086 CPU 有 14 个 16 位寄存器,按功能分为几组。

核心思想

CPU 操作数据要么直接用立即数,要么从寄存器取,要么从内存取。寄存器最快,但数量有限(只有14个)。 相关内容详见 02-内存寻址

通用寄存器(4个)

AXBXCXDX 这四个寄存器用于存放一般性数据,每个都可以拆成两个独立的 8 位寄存器使用:

16位高8位低8位特殊用途
AXAHAL累加器,乘除法默认使用
BXBHBL基址寄存器,常用于内存寻址
CXCHCL计数器,[[07-转移指令与循环
DXDHDL数据寄存器,乘除法和 [[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位 + 偏移)

段寄存器名称默认搭配作用
CSCode SegmentIP指向当前执行的代码段
DSData SegmentBX/SI/DI/[idata]指向数据段
SSStack SegmentSP/BP指向栈段(详见 06-栈
ESExtra Segment需显式指定附加段,用于串操作等

关键理解

内存里存的内容到底是”指令”还是”数据”,不取决于内存本身,而取决于哪个段寄存器指向它

  • CS:IP 指向的内存 → 被当作指令执行
  • DS 指向的内存 → 被当作数据读取
  • SS:SP 指向的内存 → 被当作栈操作 同一块内存,用不同方式解读,结果完全不同。

控制寄存器

寄存器全称作用
IPInstruction Pointer存放下一条指令的偏移地址,和 CS 配合(CS:IP 指向下一条指令)
SPStack Pointer栈顶指针,和 SS 配合(详见 06-栈
FLAGS标志寄存器存储 CPU 状态标志(详见 09-标志寄存器

不能直接赋值的寄存器

  • CS 不能用 mov 赋值,只能通过 jmpcall/retint 等转移指令修改。如果允许 mov cs, ax,执行完这一行后 CS 瞬间改变,CPU 会找不到下一条指令而崩溃。
  • 所有段寄存器都不能直接赋值,必须用通用寄存器中转:
; mov ds, 1000H    ; ❌ 错误!不能直接给段寄存器赋值
mov bx, 1000H
mov ds, bx         ; ✅ 正确,通过 BX 中转

变址寄存器

寄存器名称用途
SISource Index源变址寄存器,常用于串操作的源地址
DIDestination Index目的变址寄存器,常用于串操作的目的地址
BPBase 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 后缀是十六进制:1000H0ABCH
  • B 后缀是二进制:00010000B
  • 以字母(A-F)开头的十六进制数,前面必须加 00ABCH 而不是 ABCH
  • 字符串用单引号:'a''abc'

相关