8086结构
- 8086的基础信息
-
字长16bit,因此PC每次递增是PC=PC+2
-
段寄存器(用于计算逻辑地址)
-
代码段寄存器CS:是段基地址,当地址指向代码段时,PC = (CS<<4) | offset(通常为IP)
- 数据段寄存器DS:是段基地址,当地址指向数据段时,ADDR = (DS<<4) | offset(通常为DX)
- 堆栈段寄存器SS:是段基地址,当地址指向堆栈段时,ADDR = (SS<<4) | offset(通常为BP和SP)
- 附加段寄存器ES:是段基地址,当地址指向附加段时,ADDR = (ES<<4) | offset(通常为SI和DI)
-
注:offset由具体指令提供,比如MOV AX [BX]表示offset由BX寄存器提供
-
通用寄存器
-
AX:累加器(包含AL/AH)
- CX:计数寄存器(包含CL/CH)
-
DX:数据寄存器(包含DL/DH)
-
BX:表示数据段的offset(包含BL/BH)
- BP:表示堆栈段的offset
-
SP:堆栈顶指针
-
SI:数据结构中作为源地址指针(数组中作为行偏移);有时用于IO寻址
- DI:数据结构中作为目的地址指针(数组中作为列偏移);有时用于IO寻址
寻址模式
- 注:该寻址模式默认发生在实模式下(此外还有保护模式)
- offset表示:(比如1234H、[1234H])
-
1234H表示一个立即数,而[1234H]表示1234H地址处的值(这包含一次访存)
-
完整地址表示:(比如DS:BX、DS:[BX+AL])
- XX:YY,XX为段寄存器,XX:YY效果等同于YY
-
XX:[YY],XX为段寄存器,XX:[YY]效果等同于[YY](这包含一次访存)
-
立即寻址:MOV AX, 1234H
-
直接寻址:MOV AX, [1234H]
-
寄存器直接寻址:MOV AX, BX
- 寄存器间接寻址:MOV AX, [BX]
-
寄存器相对寻址:MOV AX, [BX+5]或5[BX]
-
基址变址寻址:MOV AX, [BX+SI]或[BX][SI]
-
相对基址变址寻址:MOV AX, [BX+SI+5]或5[BX][SI]
-
隐含寻址:MUL BL(这里源寄存器为BL和AL,目的寄存器为AX)
-
IO端口直接寻址:IN AL, 60H(PIO访存)
- IO端口间接寻址:IN AL, DX(PIO访存)
- 注:MMIO访存可以直接由[dev_addr]做到,无需使用IN/OUT指令
8086微架构
1. 模式
- 最小工作模式:单处理器模式,所有控制信号由微处理器产生

- 最大工作模式:最大模式为多处理器模式,部分控制信号由外部总线控制器产生

2. 总线
- 组成:地址总线、数据总线、控制总线
3. 工作时序
- 注:该微架构默认发生在最小工作模式下

| CLK | 时钟信号 | 高电平有效 |
|---|---|---|
| A19/S6-A16/S3 | Bit6-bit3状态信号 | 状态信号 |
| AD7-AD0 | Bit7-bit0数据信号(可复用) | 数据信号 |
| ALE | 地址锁存信号 | 低电平无效 |
| IO/$\overline M$ | 接口/存储器访问控制位 | 高访问IO,低访问内存 |
| $\overline {RD}$ | 读数据操作使能信号 | 低允许读 |
| DT/$\overline R$ | 数据访问方向控制位 | 高IO到CPU,低内存到CPU |
| $\overline {DEN}$ | 允许数据读写信号 | 低允许读写 |
- IO/$\overline M$信号:8086和8088不同,这里是8086
- 一次取指或读内存的过程
- 发出地址:内存地址/IO端口地址
- 发出读控制信号
- 接收传输的数据
指令系统
1. 基本指令
- 数据传送
- MOV、XCHG
- PUSH、POP
- XLAT
- CBW、CWD
- IN、OUT
- 算术运算
- ADD、ADC
- SUB、SBB、DEC、CMP、NEG
- MUL、IMUL、DIV、IDIV
- 逻辑运算
- AND、OR、NOT、XOR、TEST
- 移位操作
- SHL、SAL、SHR、SAR
- SOL、ROR、RCL、RCR
2. 串操作
- 原理
- 源串:一般存放在数据段,偏移地址由SI指定。允许段重设。
- 目标串:必须在附加段,偏移地址由DI指定。
- 串信息:长度由CX指定,操作方向由DF状态位决定(DF=0增地址方向,DF=1减地址方向)

- 串操作指令只能完成:执行单次操作+修改地址指针(SI和DI)
-
重复前缀(REP、REPZ、REPNZ、REPE、REPNE)可以完成:修改串长度+再执行一次串操作指令,直到完成
-
串操作指令
- MOVS、CMPS、SCAS、LODS、STOS(加上B/W的后缀可以处理字节/全字数据)
控制指令
- 跳转
-

-
循环
-
LOOP、LOOPZ、LOOOPNZ
-
过程调用
- 段内调用原理(CALL PROC+RET)
- 先将原IP作为caller返回地址,存入栈中(SP=SP-2;SS:SP=IP)
- 再跳转到子程序入口(IP=func_offset)
- 段间调用原理(CALL FAR PTR+RETF)
- 先将原CS:IP作为caller返回地址,两者都存入栈中(SP=SP-2;SS:SP=IP;SP=SP-2;SS:SP=CS)
- 再跳转到子程序入口(CS:IP=func_seg:func_offset)
-
指令:CALL
-
中断控制
- 中断原理
- 保存环境
- 将FLAGS存到栈中
- 将下一条指令(PC+2)的CS:IP存到栈中(SP=SP-2;SS:SP=IP;SP=SP-2;SS:SP=CS)
- 根据中断号查表(中断向量表),得知中断程序的入口地址
- 再跳转到中断入口(CS:IP=int_seg:int_offset)
- 中断指令:INT n(中断号)、IRET
汇编语言设计
1. 基础
- 变量定义:DB、DW、DD、DQ、DT
- veriable DB 10(veriable开始的1个字节,赋值为10)
- list DB 10,20,30(list开始的1个字节,赋值为10、20、30)
-
nums DW 1000h,2000h(nums开始的两个字节,赋值为...)
-
重复操作符:DUP
- veriable DB 10 DUP(0)(veriable开始的10个字节,赋值为0)
- 随机值:?
- veriable DB ?
- veriable DB 10 DUP(?)
- 调整变量偏移:ORG
- 表达式定义:EQU
- CONSTANT EQU 100(用CONSTANT代替表达式100)
2. 段设计
- 定义逻辑段
- 开始:段名 SEGMENT
- 设定段信息:ASSUME 段寄存器:段名 [,段寄存器:段名,...]
- 结束:段名 ENDS
- 定义过程段
- 开始:过程名 PROC [NEAR/FAR]
- 过程返回:RET/RETF
- 结束:过程名 ENDP
- 定义宏(汇编时直接展开)
- 开始:宏名 MACRO
- 结束:ENDM
3. 系统调用
- 调用BIOS服务(使用不同中断号)
- 中断号10H:视频服务
- 中断号13H:磁盘服务
- 中断号16H:键盘服务
- 调用DOS服务(使用固定中断号21H,将AH当作功能号来分发服务)
- 功能号01H:输出回显字符(返回AL=字符)
- 功能号02H:输出字符(输入DL=字符;返回AL=DL)
- 功能号09H:输出字符串(必须以\$结尾)(输入DX=字符串)
- ...(文件操作等服务)
输入输出

- 8086的外设映射方式为PIO和MMIO
- MMIO访存可以直接由[dev_addr]做到
-
PIO需要使用IN/OUT指令
-
总线视角的外设访问
- 方式判断:总线中用IO/$\overline M$来区分是PIO还是MMIO
- 地址与控制信号:读/写有效,进入PIO/MMIO有效周期。此时地址总线A0-A15有效。
-
地址译码
- 当芯片只有一个端口时,用全部地址与端口地址比较,得到对应端口号(精确比较)
- 当芯片有多个端口时,地址高位用于译码,得到端口区域;然后用低位地址与区域内的端口地址比较,得到端口号(先模糊比较,再精确比较)
-
DMA外设
-
传输模式
- 突发模式:块传输。DMA优先级最高。连续占用总线,直到完成整个块的传输才结束(不管DREQ信号是否有效)。由于连续占用总线,会导致CPU和总线其他设备的短暂阻塞。
- 需求模式:请求传输。DMA优先级较高于CPU。如果DREQ有效,则连续占用总线;如果无效则将总线归还。
- 周期偷取模式:单元传输。DMA优先级较低于CPU。将一个DMA请求分为多次单元传输,当CPU释放总线后,只偷取一个访存周期来传送一个单元(一般是1Byte或1Word)。
- 透明模式。
-
中断
- 内异常(异常事件、自陷事件)
- 外中断(可屏蔽中断INTR、非屏蔽中断NMI)
接口电路
1. 数字接口电路
- 定时计数器8253
- 并行接口8255
- 中断控制器8259
2. 模拟接口电路
- 暂时略