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 | jmp 2AE3:3 |
DS 寄存器
DS(Data Segment) 寄存器,通常用来存放要访问数据的段地址。如下:
1 | mov bx, 1000H |
通过 mov al, [0]
完成了数据从 1000:0
单元到 al 的传送,段地址取的是 ds 寄存器中的 1000H
mov 指令
mov 指令有如下几种格式:
1 | mov 寄存器, 数据 |
栈机制
入栈,push ax
表示将寄存器 ax 中的数据送入栈中
出栈,pop ax
表示从栈顶取出数据送入 ax
8086 CPU 的入栈和出栈操作都是以 字为单位进行的
段寄存器 SS:栈顶的段地址。寄存器 SP :栈顶的偏移地址
任何时刻,SS:SP
指向栈顶元素,push 指令和 pop 指令执行时,CPU 从 SS 和 SP 中得到栈顶的地址。
push 指令的执行,有两个步骤:
SP = SP - 2
,SS:SP
指向当前栈顶前面的单元,以当前栈顶前面的单元为新的栈顶- 将 ax 中的内容送入
SS:SP
指向的内存单元处,SS:SP
此时指向新栈顶
pop 指令的执行,有两个步骤:
- 将
SS:SP
指向的内存单元处的数据送入 ax 中 SP = SP + 2
,SS:SP
指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶
注意:8086 CPU 不保证我们对栈的操作不会超界,需要我们自己保证 push、pop 不出栈的范围。
1 | push 寄存器 / 段寄存器 / 内存单元 |
注意
Intel 处理器不允许将一个立即数传送给段寄存器,他只允许如下指令:
1 | mov 段寄存器, 通用寄存器 |