寄存器

8086CPU 的寄存器都是16 位的。通用寄存器包括:AX、BX、CX、DX、SI、DI、BP、SP,他们可以存放一般性的数据。其中 AX、BX、CX、DX 这 4 个寄存器可以拆成两个 8 位寄存器。比如:AX 可分为 AH 和 AL。

字:记为 word,一个字由两字节组成。

8086 的物理地址计算方法

8086 是 16 位 CPU,也就是说,在 8086 内部,能够一次性处理、传输、暂时存储的信息的最大长度是 16 位的。

8086 CPU 有 20 位地址总线,可以传送 20 位地址,达到 1MB 的寻址能力。但是 8086 CPU 又是 16 位结构,因此 8086CPU 采用一种在内部用两个 16 位地址合成的方法来形成一个 20 位的物理地址。如下:

1
物理地址 = 段地址 * 16 + 偏移地址

他的含义是:CPU 在访问内存时,用一个基础地址(段地址 * 16)和一个相对于基础地址的偏移地址相加,给出内存单元的物理地址。

段地址 * 16 必然是 16 的倍数,所以一个段的起始地址也一定是 16 的倍数;偏移地址为 16 位,16 位地址的寻址能力为 64KB,所以一个段的长度最大为 64KB。

CS 和 IP 寄存器

CS(Code Segment) 寄存器:代码段寄存器。IP 寄存器:指令指针寄存器。他们指示了 CPU 当前要读取指令的地址。也就是说,在 8086PC 机中,任意时刻,设 CS 中的内容为 M,IP 中的内容为 N,8086CPU 将从内存 M * 16 + N 单元开始,读取一条指令并执行。

mov 指令不能设置 CS、IP 的值。可以使用 jmp。若想同时修改 CS、IP 的内容,可使用:jmp 段地址:偏移地址。如果仅想修改 IP 的内容,可用:jmp 某一合法的寄存器 来完成。

1
2
jmp 2AE3:3
jmp ax

DS 寄存器

DS(Data Segment) 寄存器,通常用来存放要访问数据的段地址。如下:

1
2
3
mov bx, 1000H
mov ds, bx
mov al, [0]

通过 mov al, [0] 完成了数据从 1000:0 单元到 al 的传送,段地址取的是 ds 寄存器中的 1000H

mov 指令

mov 指令有如下几种格式:

1
2
3
4
5
mov 寄存器, 数据
mov 寄存器, 寄存器
mov 寄存器, 内存单元
mov 内存单元, 寄存器
mov 段寄存器, 寄存器

栈机制

入栈,push ax 表示将寄存器 ax 中的数据送入栈中

出栈,pop ax 表示从栈顶取出数据送入 ax

8086 CPU 的入栈和出栈操作都是以 字为单位进行的

段寄存器 SS:栈顶的段地址。寄存器 SP :栈顶的偏移地址

任何时刻,SS:SP 指向栈顶元素,push 指令和 pop 指令执行时,CPU 从 SS 和 SP 中得到栈顶的地址。

push 指令的执行,有两个步骤:

  • SP = SP - 2SS:SP 指向当前栈顶前面的单元,以当前栈顶前面的单元为新的栈顶
  • 将 ax 中的内容送入 SS:SP 指向的内存单元处,SS:SP 此时指向新栈顶

pop 指令的执行,有两个步骤:

  • SS:SP 指向的内存单元处的数据送入 ax 中
  • SP = SP + 2SS:SP 指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶

注意:8086 CPU 不保证我们对栈的操作不会超界,需要我们自己保证 push、pop 不出栈的范围。

1
2
push 寄存器 / 段寄存器 / 内存单元
pop 寄存器 / 段寄存器 / 内存单元

注意

Intel 处理器不允许将一个立即数传送给段寄存器,他只允许如下指令:

1
2
mov 段寄存器, 通用寄存器
mov 段寄存器, 内存单元