MCP-Chapter-03
8086 寻址方式
存储器体系结构
不管实际存储容量是多少,CPU 都默认自己有无限大的存储空间(即理想存储情况)。
graph LR
A[寄存器] --> B[Cache]
B --> C[主存]
C --> D[辅存]
局部性原理
-
时间局部性:刚用过的数据,很可能马上还要再用一次。
-
空间局部性:刚用过的数据,它旁边的数据,很可能马上也要被用。
工作流程:
graph LR
A[CPU 需要数据] --> B[访问Cache查询]
B -- 有数据 --> C{Cache结果}
C -- 命中 Hit --> D[CPU 立即从Cache获取数据<br>皆大欢喜,速度很快]
B -- 无数据 --> E{Cache结果}
E -- 未命中 Miss --> F[CPU 停工等待]
F --> G[Cache 向主存请求数据]
G --> H[主存返回数据<br>(包含所需数据及其邻近小块)]
H --> I[Cache 保存数据并传给CPU]
I --> J[CPU 继续工作]
寻址方式
概述
| 寻址方式 | 操作数位置 | 细分分类 | 举例 |
|---|---|---|---|
| 立即寻址 | 在指令代码中 | — | MOV AX, 1234H |
| 寄存器寻址 | 在寄存器中 | — | MOV AX, BX |
| 存储器寻址 | 在主存中 | 直接寻址 | MOV AX, [2000H] |
| 寄存器间接寻址 | MOV AX, [BX] | ||
| 寄存器相对寻址 | MOV AX, [BX+10H] | ||
| 基址变址寻址 | MOV AX, [BX+SI] | ||
| 相对基址变址寻址 | MOV AX, [BX+SI+20H] | ||
| I/O端口寻址 | 在IO端口中 | 直接端口寻址 | IN AL, 60H |
| 间接端口寻址 | MOV DX, 378HOUT DX, AL |
注意: 寻址方式是针对操作数而言的。即寻找对应表述地址里面的数据(不管是立即数,还是从寄存器、主存里找到对应的数据)。
立即寻址
操作数(数据)作为指令机器码的一部分,存放在内存的代码段中。
MOV AX 1234H:其中的1234H即为立即数,此种寻址方式即为立即寻址。
立即数只能作为源操作数,只能传给存储器和通用寄存器,不能直接给段寄存器。
寄存器寻址
用寄存器代号代替对应寄存器内部放置的数据。
MOV AX BX:把BX里面的数据给到AX里面,用寄存器代号BX来代替里面的数据。
源寄存器和目的寄存器的类型要一样,
存储器寻址
8086 的物理地址为:段地址 + 偏移地址
其中:偏移地址 = 有效地址 = 基址(BX BP) + 变址(SI DI) + 位移量
段地址基本上不会直接出现在指令代码中,会根据偏移地址中使用的寄存器默认匹配段。
以下展示的各种各样的存储器寻址方式其实就是这个公式里面三个元素的排列组合,记忆方式很反人类:
| 寻址方式 | 组合 |
|---|---|
| 直接寻址 | 偏移地址 |
| 寄存器间接寻址 | 基址(我们把 BX 默认为基址,而不是认为是把偏移地址存到 BX 寄存器里) |
| 寄存器相对寻址 | 基址+偏移地址 |
| 基址变址寻址 | 基址+变址 |
| 相对基址变址寻址 | 基址+变址+偏移地址 |
直接(位移量)寻址

存储器直接寻址示意图
如MOV AL,[2000H],这里不需要PTR。实际使用过程中经常使用MOV AL,DATA1也就是变量来直接寻址。
存储单元之间不能互相直接操作数据。如果将data2处数据放到data1,需要AL这种通用寄存器来过渡。
寄存器间接寻址

只能用BX,SI,DI,如[BX],即把偏移量提前存在了 BX 寄存器里面了,具体语句:
MOV BX, OFFSET DATA1 ; 把 DATA1 的地址赋予 BX
MOV AL,[BX]
寄存器相对寻址
EA(偏移量)= 基址/变址寄存器 + 位移量
MOV AX, [BX+1000H]

基址变址寻址
EA = (BX 或 BP) + (SI 或 DI)
相对基址变址寻址
使用完全体公式进行寻址:偏移地址 = 有效地址 = 基址(BX BP) + 变址(SI DI) + 位移量
I/O 端口寻址
CPU访问I/O端口,只能使用两条专属指令:IN (输入) 和 OUT (输出)。分为直接端口寻址(直接使用 16 进制数进行寻址端口)与间接端口寻址(从通用寄存器寻址)
8086 指令系统
传送类指令

- 除了标志传送指令
SHAF和堆栈操作指令POPF外,其余传送指令不影响状态标志。 - 语法规则:
- 立即数只能做源操作数
- 类型要一致
- 类型要明确
- DS SS ES 做目的操作数时,立即数不能做源操作数
- CS、IP不能做目的操作数
- 两存储器单元之间不能互相操作,指令语句中两变量也不能直接运算
通用传送指令 MOV
MOV AX,BX
MOV (Move) 其实有误导性。它并不是移动,而是复制。执行 MOV AX, BX 后,BX 的内容保持不变。

取有效地址指令 LEA
其源操作数必须是内存操作数(即用[]括起来的那种地址,即偏移地址)。
LEA 的功能就是 ==计算== 源操作数(即有效地址),然后把这个地址数值传送到目的寄存器中,由于是直接写进目的寄存器里面,没有普通算术指令的写回周期,是更加高效的加法运算指令。
LEA AX,TABLE1
;将源操作数的有效地址(EA)放到寄存器中
MOV BX,OFFSET DATA1
;等价于下面
LEA BX,DATA1
;但要与下面这个语句区分开
MOV BX,DATA1;这个意思是将DATA1处内容放到BX
;此时data1处类型不明确,所以
MOV BX,WORD PTR DATA1