✅ 通过对 【计算机与UNIX汇编原理 ① ~ ⑫】的学习,我们已经大致掌握了汇编程序设计的相关知识
接下来,我将其分栏名改为 【计算机原理与接口技术(UNIX) 】,重点将放在 “计算机原理与接口技术” 上
IN/OUT System ☁️
上一篇文章链接:【计算机原理与接口技术(UNIX)⑭】——再讲存储器系统【位、字扩展法 + 详细例题】.
下一篇文章链接:【计算机原理与接口技术(UNIX)⑯】——中断系统 [ 2万5千字总结、8259A ].
一、输入/输出系统的基础知识点
● 在前面,我们已经学习了《总线与总线标准》、《存储器系统》两章前驱知识,现在 “交通”(总线)、“数据站”(存储器),“处理站”(CPU,前面已经学过)、“港口货物站”(外设接口)都已经学习过了,接着,我们就要来学习它们之间的交换机制了,即马上要学习的 “输入/输出系统”。
● 输入输出系统:指的是(微型)计算机系统中主机与外设进行数据交互的系统。
● 主机通过输入/输出接口与外设连接,在接口电路和驱动程序下进行信息交换。
1.1 接口电路
● 接口:是 CPU 与外部设备交换信息的中转站。
● 接口电路的作用:【可视化图如下】
① CPU数据 → 输出接口电路 → 输出设备
② CPU ← 输入接口电路 ← 输入设备数据
● 接口电路的功能:
① 应具有数据暂存功能(数据缓存器[输入]、数据锁存器[输出])
② 应有端口地址译码器(便于使用IN、OUT指令读写数据)
③ 与外设之间有联络功能
④ 有中断管理能力
⑤ 有数据转换功能(并 → 串、串 → 并)
1.2 输入输出端口
● 端口:是接口电路中,能与 CPU 交换信息(使用IN、OUT)的寄存器。
● 端口分类:
① 数据端口:存放 CPU 向外设输出或外设输入的数据。【注意:接口电路必须具有数据端口】
② 控制端口:存放控制信息——控制接口电路、外设的工作。
③ 状态端口:存放状态信息——反映外设的状态。
● 每个端口,系统都为它编了一个地址,系统只要给出某个地址,通过译码电路,就能找到相应的 I/O 接口电路中的端口寄存器。
● 问题:怎么区分 系统给出的地址 是内存单元地址还是 I/O 端口寄存器的地址?
解决方案:合理安排 I/O 端口寄存器的编址方式。
● 端口的编址方式:
① 端口和存储单元统一编址(也称为存储器映像方式)
方式:把端口和存储单元等同看待,统一编址。
特点:凡访问存储单元的指令都可访问 I/O 端口、端口地址占用存储空间。
② I/O 端口独立编址
方式:I/O 端口和存储器分别使用两个地址空间,单独编址和译码。
特点: I/O 端口不占用存储空间、CPU要有专用的 I/O 指令、端口地址译码需要专门的控制电路和译码电路
-
端口分类:
① 端口和存储单元统一编址(也称为存储器映像方式)
方式:把端口和存储单元等同看待,统一编址。
特点:凡访问存储单元的指令都可访问 I/O 端口、端口地址占用存储空间、执行存储器的指令往往比那些为独立的 I/O 操作而专门设计的指令慢。
② I/O 端口独立编址
方式:I/O 端口和存储器分别使用两个地址空间,单独编址和译码。
特点:I/O 端口不占用存储空间、CPU要有专用的 I/O 指令、端口地址译码需要专门的控制电路和译码电路。 -
PC系列机的端口一般采用独立编址:
① 从 8088 ~ 奔腾微处理器,设计时用 A15 ~ A0 的低 16 位地址寻址 I/O 端口。所以, CPU 的端口寻址能力为 216=65536个。
② 基于微处理器的 PC 系列,实际使用 A9 ~ A0 做 I/O 地址。所以,PC 系列机 I/O 端口地址最多为 210=1024个。
注意:这 1024 个口地址, 系统本身(主板上, 以及常规 I/O 接口)已经占用了一部分。 且端口地址( I/O 空间 )没有分段的概念。
1.3 常用的输入输出指令
1.3.1 直接寻址的 I/O 指令
● 当端口地址为 1 字节(8bit)时,可采用直接寻址方式。(8 位地址最多可访问 256 个端口)
■ 输入指令的格式:
IN AL,PORT ; 将 PORT 端口的内容输入到 AL 寄存器
IN AX,PORT ; 将 PORT ~ PORT+1 端口的内容输入到 AX 寄存器
IN EAX,PORT ; 将 PORT ~ PORT+3 端口的内容输入到 EAX 寄存器
■ 输出指令的格式:
OUT PORT,AL ; 将 AL 寄存器的内容输出到 PORT 端口
OUT PORT,AX ; 将 AX 寄存器的内容输出到 PORT ~ PORT+1 端口
OUT PORT,EAX ; 将 EAX 寄存器的内容输出到 PORT ~ PORT+3 端口
● 样例:
IN AL,61H ; (√)
OUT 61H,AL ; (√)
IN AX,100H ; (×), 因为 100H 超过了 8 位所能表示的地址(即 100H > FFH)
1.3.2 DX 间址的 I/O 指令
● 当端口地址为 2 字节时,用间接寻址方式,此时最多可访问 216 = 65,536 个端口,且端口地址必须放在寄存器 DX 中。
■ 输入指令的格式:
IN AL,DX ; 将 AL 的内容输出到 DX 指向的端口
IN AX,DX ; 将 AL 的内容输出到 DX 指向的端口;再将 AH 的内容输出到 DX+ 指向的端口
IN EAX,DX ; 将 EAX 中的双字输出到 DX ~ DX+3 指向的 4 个端口
■ 输出指令的格式:
IN AL,DX ; 从 DX 指向的 1 个端口中读一个字节输入到 AL 寄存器
IN AX,DX ; 从 DX ~ DX+1 指向的 2 个端口中读一个字输入到 AX 寄存器
IN EAX,DX ; 从 DX ~ DX+3 指向的 4 个端口中读一个双字输入到 EAX 寄存器
● 样例:
MOV DX,3F8H
IN AL,DX ;从 3F8H 端口取数 → AL
● 注意:I/O 指令只能在端口和 AL、AX、EAX 之间交换信息,且用 DX 间址时不能使用方括,即不能写成:IN AL,[DX]
。
二、系统与输入输出设备的信息交换方式
● 微机系统与 I/O 端口的信息交换有四种方式:无条件传送、查询方式、中断方式、DMA方式。
2.1 无条件传送方式
● 无条件传送方式:假设外设已准备好,即输入数据已准备好,或输出设备空闲,此时 CPU 可以直接用IN
或OUT
指令完成与接口之间的数据传送。
-
无条件传送的输入方式:
① 当 CPU 未执行输入指令时,I/O 读信号 I O R ‾ \overline{IOR} IOR 无效,暂存器(三态缓冲器)为高阻状态,实现了外部数据与内部数据总线的隔离。② 当 CPU 执行输入指令,且外部数据已经准备好时,I/O 读信号 I O R ‾ \overline{IOR} IOR 有效,输入数据通过三态缓冲器(非高阻状态)到达数据总线,供 CPU 读取。
● 对上面张图的说明:粗的箭头线代表有很多根线,细的线代表传输 1 bit
数据的线。
-
无条件传送的输出方式:
① 当 CPU 未执行输出指令时,I/O 写信号 I O R ‾ \overline{IOR} IOR 无效,锁存器(三态缓冲器)为高阻状态,实现了外部数据与内部数据总线的隔离。② 当 CPU 执行输入指令,且 CPU 数据已经准备好时,I/O 写信号 I O R ‾ \overline{IOR} IOR 有效,输出数据通过锁存器(非高阻状态)到达 I/O 端口,供外设读取。
● 如果上一次的数据在锁存器中未及时取走,则新输出的数据会改变上一次输出的数据状态,造成输出数据的丢失。
2.2 查询方式
- 查询方式:
① 采用查询方式输入数据前,CPU 要查询输入数据是否准备好。
② 采用查询方式输出数据前,CPU 要查询输出设备是否空闲。
③ 只有确认外设已具备了输入或输出的条件后,才能用IN
或OUT
指令完成数据的传送。
2.2.1 查询方式输入
● 查询式输入接口电路:
-
对上面张图的说明:
① 输入设备准备好数据后,先发出输入选通信号,一方面把数据送入数据锁存器(也称为数据缓冲器),另一方面使状态标志触发器置
1
。② 状态标志是一个 “
1bit
信息”,它接在 CPU 数据线的某一位上(我们不妨设其接在 D7 位)③ CPU 将会先读取状态端口(即图中的正中红色字体部分,注:细线代表
1bit
数据),查询 D7 位是否为1
,若是则表示输入数据已经准备好,然后读取数据端口(注:粗线代表8bit
数据),取走输入数据(8 bit
),同时将状态标志触发器复位。④ 若不是
1
,则会一直查询,空转…一直不是1
,就一直查询,直到是1
…
● 样例如下:
"设状态端口地址 = 200H,数据端口地址 = 201H,假如我们要将 数据端口地址对应的数据 传入到 CPU的数据总线 上。"
则核心代码如下:
RSCAN:
MOV DX, 200H ; 传 状态端口地址 到 DX 寄存器中(间址)
IN AL, DX ; 读取状态口地址对应的外设信息
TEST AL, 80H ; 测试测试外设是否已经准备好(通过D7位检测)
JZ RSCAN ; 如果外设没准备好, 就继续检测
MOV DX, 201H
IN AL, DX ; 将 数据端口地址对应的外设信息 输入到 CPU的数据总线 上
2.2.2 查询方式输出
● 查询式输出接口电路:
-
对上面张图的说明:
① 输出设备空闲时,将状态标志触发器置
0
。② 输出数据前,CPU 先从状态端口读取状态信息(假设其接在数据线D0位,如图右下角所示)。
③ 当 D0 = 0 时,表示输出设备空闲,然后 CPU 对数据端口执行输出指令,“数据端口选中” 信号一方面把输出数据写入锁存器,另一方面使状态标志触发器置
1
,并告知输出设备。④ 若 D0 = 1 ,则会一直查询,空转…一直不是
0
,就一直查询,直到是0
…⑤ 输出设备取走当前数据后,会向接口发送 “确认”(ACK,acknowledge)信号,使状态标志触发器置
0
。
● 样例如下:
"设状态口地址 = 数据口地址 = 200H,假如我们要将 CPU的数据总线上的数据 传入到 外设。"
则核心代码如下:
TSCAN:
MOV DX, 200H ; 将 状态端口地址 送到 DX 寄存器中(间址)
IN AL, DX ; 读取状态口地址对应的外设信息
TEST AL, 1 ; 测试测试外设是否空闲(通过D0位检测)
JNZ TSCAN ; 如果外设未空闲, 就继续检测
MOV DX, 200H ; 将 数据端口地址 送到 DX 寄存器中(间址)
MOV AL, 数据 ; 将 数据 传入到 AL 中
OUT DX, AL ; 将 AL中的数据 输出到 数据端口地址对应的外设设备 上
2.3 中断控制方式
● 在查询方式中,CPU 通过不断地读取状态信息来了解状态,故导致 CPU 的利用率不高。
● 而且在有多个外设的系统中,一般会有多个外设要求 CPU 为它服务,且是随机的。若采用查询式方式就不能保证系统实时地对外设做出响应。
● 为了提高 CPU 的效率,使系统有实时性能,导致了中断处理技术的产生。
-
中断方式的执行流程:
① 在外设没有作好数据传送准备时,CPU 可执行与传送数据无关的其它指令。
② 当外设作好传送准备后,主动向 CPU 发送请求中断。
③ 若 CPU 响应这一请求,则暂停正在运行的程序,转入中断服务程序,完成数据传送。
④ 待服务完毕后,CPU 自动返回并执行原来运行的程序。
-
对上面张图的说明:【中断方式输入接口电路】
① 输入设备准备好数据后,先发出输入选通信号,一方面把数据送入数据锁存器(也称为数据缓冲器),另一方面使中断请求触发器置1
。② 如果此时 CPU 相应这个请求,一方面会向右下方的线路发出一个
允许
信号,接着就会产生中断信号“INTR
”;另一当面会向右上方的线路就绪
信号,那么就会使得中断请求触发器置0
(使它关闭,避免重复发送中断请求)、也会使得三态缓冲器置1
(使它打开,一会就可以输入数据了)。③ CPU 接受到
INTR
后,就会中断当前原程序,转而执行 “中断服务程序”。④ 待服务完毕后,那些触发器、缓冲器将会复位,CPU 自动返回并执行原来运行的程序。
2.4 直接存储器存取方式
● 采用中断方式进行数据传送,可以提高 CPU 的利用率。但是,中断传送是由 CPU 通过程序来实现的,每次执行中断服务子程序都需要保护断点,而且在中断服务子程序中,需要保护现场,为中断源服务,中断服务结束后还要恢复现场,所以 CPU 需要执行若干指令来完成上述工作。
● 故对于高速外设来说(如高速磁盘驱动器),中断方式往往就不能满足要求了。这个时候就需要 DMA (全称为 Direct Memory Access)。
● 直接存储器存取方式(DMA):直接用硬件实现在外设与内存之间的数据交换,而不用通过 CPU(间接交换)。这种数据传送速度的上限就取决于存储器的工作速度,一般速度都很快。
三、DMA 控制器
● DMA (Direct Memory Access):直接存储器存取,习惯上称 DMA 传送。即用硬件实现 存储器和存储器之间 或 存储器与I/O设备之间 的直接进行的高速数据传送,而不需 CPU 的干预。
● DMAC:DMA 控制器。它是实现 DMA 传送的核心芯片
● 专用术语:
① DMA 读传送:在 DMAC 控制下, 读取RAM的内容 → I/O端口。
② DMA 写传送:I/O端口信息 → 系统 RAM 某单元。
③ 存储单元读/写传送:在 DMAC 控制下,实现系统 RAM <一> RAM。【注意:在 PC 系列机中禁止 RAM <一> RAM 的传送。】
● 系统的三总线分别受到 CPU 和 DMAC 的控制。
● CPU 可以向地址总线、数据总线、控制总线上发送信息,DMAC 也可以向地址总线、数据总线、控制总线上发送信息。但同一时间,三总线只能受一个器件的控制,所以两者之间必须一个 “联络信号”。
-
DMA 传送的流程:
① I/O 端口首先向 DMAC 发出 “DMA 请求” 信号,请求 DMAC 为其传送数据。② DMAC 检测到有 DMA 请求之后,即向 CPU 提出总线保持请求 (请求 CPU 脱离总线)。
③ CPU 执行完当前指令的当前总线周期之后,便脱离系统总线,并向 DMAC 发出 “总线保持响应” 信号(即 HLDA,这是 CPU 对 HOLD 信号的响应信号,它会对 HOLD 信号做出响应,使 HLDA 输出高电平)。
④ DMAC 收到 “总线响应” 信号之后,便接管系统总线的控制权,并向 I/O 接口发出 DMA 响应信号。
⑤ 若进行 DMA 读传送:DMAC 把 RAM 地址 → 地址总线上,然后 DMAC 发出存储器读命令和 I/O 写命令;若进行 DMA 写传送:DMAC 把RAM地址 → 地址总线上,然后 DMAC 发出 I/O 读命令和存储器写命令。
⑥ 当预定的字节数全部传送完毕,DMAC 便脱离系统总线,CPU 再次控制系统总线,继续执行被中断的当前指令的其他总线周期。
-
DMA 传送与中断方式的比较:
① DMA 传送比中断传送的速度快。(DMA 传送一字节只占用 CPU 的一个总线周期,而中断传送方式是由 CPU 通过程序来实现的,每次执行中断服务子程序, CPU 都要保护断点,在中断服务子程序中,也需保护现场和恢复现场,故需要执行若干指令才能传送一字节)② DMA 响应比中断响应的速度快。(中断方式是在 CPU 的当前指令[一条指令需要执行若干个总线周期]执行完才能响应中断请求,而 DMA 方式是在 CPU 当前指令的一个总线周期执行完就可以响应 DMA 的请求了)
③ 中断请求分为内部中断和外部中断。DMA 请求的方式也有两种:硬件 DMA 请求和软件 DMA 请求。
3.1 8237A DMA 控制器
● 8237A:微型计算机系统中实现 DMA 功能的大规模集成电路控制器。
● 8237A 是具有4
个独立 DMA 通道的可编程 DMAC。
- 8237A 的基本功能:
① 在一个芯片中有4
个独立的 DMA 通道。
② 每一个通道的 DMA 请求都可以被允许或禁止。
③ 每一个通道的 DMA 请求有不同的优先级,可以是固定优先级,也可以是循环优先级。
④ 每一个通道一次传送的最大字节数为64KB
。
⑤ 它提供4
种传送方式:单字节传送方式、数据块传送方式、请求传送方式、级联传送方式。
● 8237A 的内部结构框图如下:(大致看一下即可)
● 8237A 内部寄存器分成两类:一类是4
个通道共用的,另一类是每个通道专用的。
3.1.1 8237A —— 控制寄存器
● 8237A 的4
个通道共用一个控制寄存器。编程时,由 CPU 写入控制字,而由复位信号(RESET
)或软件清除命令清除它。控制寄存器格式如下:
- 对 8237A 控制寄存器的说明:
① D0:如图所示。
② D1:如图所示。
③ D2:如图所示。
④ D3:如图所示。
⑤ D4:选择各通道 DMA 请求的优先级。
⑥ D5:如图所示。
⑦ D6、D7:确定DREQ
和DACK
的有效电平极性。
● 注意:系统机加电后,由 BIOS 完成 DMAC 的初始化,控制命令字 = 0(即各个通道禁止RAM <一> RAM)、允许读/写传送、使用正常时序、不扩展写信号、DMA 请求高电平有效、DMA 应答信号低电平有效、各通道的 DMA 请求是固定优先级(即: DREQ0
最高、REQ3
最低。 用户没有必要也不应当改变控制寄存器的内容。
3.1.2 8237A —— 方式寄存器
● 8237A 每个通道都有属于自己的一个方式寄存器,但是4
个通道方式寄存器共用一个端口地址方式选择命令字的格式如下:
● 说明:① 方式字的最低两位用于 “对通道的选择” 。(写入命令字之后,8237A 会根据 D1、D0 的编码把方式寄存器 D7 ~ D0 位的数据送到相应通道的方式寄存器中,进而确定该通道的传送方式、数据传送类型等)
● 举一个栗子:
执行命令如下:
MOV AL, 01001001B
OUT 方式寄存器口地址, AL
● 表示:对 CH1 (通道一)进行单字节读传送,自动加1
变址, 没有自动重装功能。
3.1.3 8237A —— 地址寄存器
● 每个通道都有一个16
位的 “基地址寄存器” 和一个16
位的 “当前地址寄存器”。
● 基地址寄存器存放本通道 DMA 传输时所涉及的存储区首地址或末地址,这个初始值是在初始化编程时写入的,同时也被写入当前的地址寄存器。
- 关于 DMA 传送的地址生成机制:
① 先由当前地址寄存器向地址总线提供本次 DMA 传送时的内存地址(低16
位)
② 当前地址寄存器的值在每次 DMA 传输后自动加1
或减1
,为传送写下一字节做准备。
③ 在整个 DMA 传送期间,基地址寄存器的内容一直保持不变。
④ 当通道初始化时选择了 “自动重装” 功能时,一旦全部字节传送完成时,基地址寄存器的内容会自动重新装入当前地址寄存器。
3.1.4 8237A —— 字节寄存器
● 每个通道都有一个16
位的 “基本字节寄存器” 和一个16
位的 “当前字节寄存器”。
● 基本字节寄存器存放本通道 DMA 传输时字节数的初值。(在初始化编程时,初值也被写入当前字节寄存器)
● 在 DMA 传送数据时,每传送一字节,当前字节寄存器自动减1
,当初值0
减到FFFFH
时,产生计数结束信号。
● 当通道初始化选择 “自动重装” 功能时,一旦全部字节传送完毕,基本字节寄存器的内容自动重新装入当前字节寄存器。
● 基本字节寄存器预置初值后将保持不变,也不能被 CPU 读出,而当前字节寄存器中的内容可以随时由 CPU 读出。
3.1.5 8237A —— 先/后触发器
● 8237A 只有8
根数据线,而地址寄存器、字节寄存器都是16
位。所以地址值(/字节值)需要分2
次写入。
● 先/后触发器规定了写入地址寄存器中的初值,以及写入字节寄存器中的初值的写入顺序。 先将 先/后触发器 清零,则先写入的是低8
位,后写入的是高8
位。
3.1.6 8237A —— 状态寄存器
● 状态寄存器的格式如下:
● 状态寄存器高4
位表示当前4
个通道是否有DMA
请求,低4
位表示4
个通道的DMA
传送是否结束,供 CPU 查询。
3.1.7 8237A —— 请求寄存器
● 请求寄存器是4
个通道共用的寄存器,使用时应写入请求命令字。格式如下图所示:
● 8237A 根据请求寄存器的 D2 ~ D0 位将相应通道的请求触发器置1
(或置0
),使相应通道提出 “软件 DMA 请求”。
3.1.8 8237A —— (单通道)屏蔽寄存器
● 屏蔽寄存器是4
个通道共用的寄存器,使用时应写入屏蔽命令字。格式如下图所示:
● 功能:屏蔽某一通道的 DMA 请求。
3.1.9 8237A —— 多通道屏蔽寄存器
● 多通道屏蔽寄存器也是4
个通道共用的寄存器,使用时应写入屏蔽命令字。格式如下图所示:
● 使用一个屏蔽字即可使4
个通道的屏蔽寄存器分别置1
或置0
。
3.2 8237A 在 PC 系列机中的应用
① 用2
片 8237A 级连提供7
个 DMA 通道:
● 说明:通道0
通道3
支持8
位数据传送,通道5
~ 通道7
支持16
位数据传送。通道4
作为两个 DMAC 的级联。
② 扩充 8237A 的寻址范围 (方法:增设页面地址寄存器 )
● 由于 8237A 内部地址寄存器是16
位,只能寻址64KB
(216B)。为此,在 DMA 接口电路中,以 8237A 为核心为每一通道增加了一个 “页面寄存器”,用来存放高4
位 (AT机中为高8
位)地址。
- 执行流程:
① 在执行 DMA 读写传送之前,程序会把 DMA 传送所涉及的 RAM 单元的高8
位物理地址写入相关通道的页面寄存器。
② 然后再把 RAM 单元的低16
位物理地址写入相关通道的基本地址寄存器。
③ 接着把 DMA 传送的实际字节数减1
,并写入相关通道的基本字节寄存器,从而做好初始化准备。
④ 一旦 I/O 端口有 DMA 请求,并且 DMAC 控制了系统三总线之后,由相关通道的 DMA 应答信号控制就会把页面寄存器内容送到地址总线高8
位,DMAC 再把相关通道的低16
位地址经过外部地址锁存和驱动送到低16
位地址总线上,以便选择某一存储单元。
● 页面寄存器的 I/O 端口地址如下表所示:
● 后续详细样例和编程,在学完后面的《中断系统》即可上机。
四、参考附录
[1]《微型计算机原理与接口技术(慕课板)》
清华大学出版社
上一篇文章链接:【计算机原理与接口技术(UNIX)⑭】——再讲存储器系统【位、字扩展法 + 详细例题】.
下一篇文章链接:【计算机原理与接口技术(UNIX)⑯】——中断系统 [ 2万5千字总结、8259A ].
⭐️ ⭐️