汇编语言外部设备与输入/输出

在计算机系统中,输入/输出设备是实现人机交互及机间通信的的重要组成部分。

程序、原始数据和各种现场采集到的信息,要通过输入设备输入至计算机,计算结果或各种控制信号输出给各种输出设备。由于外部设备的电气特性与计算机主机的差异,外部设备的速度也低于主机 CPU 的速度,所以为了协调外部设备和计算机主机的这些差异,计算机系统通过 I/O 硬件接口以及 I/O 控制程序对外部设备进行控制和访问。

对于系统中标准输入/输出设备的常规操作,汇编语言程序员通常使用系统提供的标准输入/输出程序,也就是 DOS 系统功能调用(INT 21H)或 BIOS(基本输入/输出子系统)调用,而不必直接使用 I/O 指令。采用这种方式进行输入/输出时,不需要考虑程序的实现细节以及输入/输出设备的特性,只要按约定准备入口参数或者从约定的出口参数取出数据即可。

但在实际应用中仅靠系统提供的标准程序是不够的,有时需要直接用 I/O 指令控制外设的输入/输出操作。

一、I/O 端口

CPU 与 I/O 设备的通信有三种信息,即控制信息、状态信息和数据信息。

  • 控制信息是从 CPU 输出到 I/O 接口的,用来控制 I/O 设备的动作,如启动或停止。

  • 状态信息是从 I/O 接口输入到 CPU 的,用来表示 I/O 设备当前的状态,如对于输入设备,通常以 READY 信号表示设备已准备好向 CPU 输入数据。对于输出设备,通常以 BUSY 信号表示设备正忙,没有空闲时间接收 CPU 输出的数据。

  • 数据信息是 CPU 与 I/O 设备真正要交换的信息,对于输入设备,数据信息是从 I/O 接口输入到 CPU。对于输出设备,数据信息是从 CPU 输出到 I/O 接口。

每一个外部设备都通过 I/O 接口部件和 CPU 相连,I/O 接口部件中应该有三种寄存器,即数据寄存器,状态寄存器和控制命令寄存器。数据寄存器用来存放数据信息;状态寄存器用来存放表示外部设备当前状态的状态信息;控制命令寄存器用来传递 CPU 发出的控制信息。

这些寄存器并不属于外部设备,而是属于计算机主机。计算机主机的 CPU 通过访问这些寄存器来实现与外部设备交换数据。在实际使用中,我们通常把接口中的这些寄存器称为设备的端口(PORT)。

为了便于 CPU 对这些端口的访问,通常给这些端口分配端口地址(即端口号)来识别的,在 80x86 微机中,端口与存储器地址完全分开,采用独立编址的方式。

I/O 端口地址空间不大,由于系统中实际外设数量很少,系统只占用了 1K 个端口中的一部分,其中一些保留给用户使用。表 1 列出了部分端口地址。

部分端口地址分配

表 1 部分端口地址分配

当 CPU 执行输入/输出指令时,指令中给出的端口地址送达地址总线,系统依据输入/输出指令就知道当前是访问 I/O 端口而不是访问存储器,而且还可以知道是输入或是输出操作。

之前介绍了两条专门的 I/O 指令与端口进行通信,即 IN 和 OUT 命令,这两条指令既可以传送字节也可以传送字,视外设端口宽度决定。这两条 I/O 指令是主机 CPU 与外部设备进行数据交换的最基本途径。即使使用 DOS 系统功能调用或 BIOS 调用,其例行程序也是用 I/O 指令实现 CPU 与外部设备的数据交换。使用 I/O 指令对端口直接进行输入/输出,需要熟悉硬件结构,程序对硬件的依赖性很强,一般来说,程序员应尽可能使用层次较高的 DOS 功能,其次才是使用 BIOS 功能,最后才是使用输入/输出指令直接操作端口访问外设。理由是使用层次较高的 DOS 功能大大方便了编程,同时也可以避免因系统底层硬件和软件的改动而导致用户程序不能正常运行。

二、I/O 的数据传送控制方式

当外设的数据传送随时可以进行而不需要 CPU 查询外设的状态后再决定时,可直接用 IN 或 OUT 指令实现 CPU 与指定的外设寄存器之间的信息传送,这叫无条件传送,电灯开关对灯泡的送电就是无条件传送。无条件传送是最简单的数据传送方式,它所需要的硬件和软件都是最节省的。当然这个外设必须随时处于准备就绪的状态才能进行无条件数据传送,否则就会出错或者数据传送无效。

例 1 PC 微机中的扬声器的驱动电路如图 1 所示,61H 端口 D1 位和定时器 2 的 OUT2 引脚作为一个与门的 2 个输入端,与门的输出端经放大器连接扬声器。可以用两种方法使扬声器发声,即与门的 2 个输入端其中一个作为控制端,设置为 1(高电平),让另一个输入端交替出现 1 和 0,就可以使扬声器发声。例如让 61H 端口的 D1 位按合适的频率交替出现 1 和 0,就可以使扬声器发声。

扬声器的驱动电路

图 1 扬声器的驱动电路

例 1 程序如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
CODE   SEGMENT

ASSUME CS: CODE

SOUND   PROC FAR

F=9999H

TIME=9999H

START:

PUSH DS

MOV  AX,0

PUSH AX

MOV  CX,F       ; 延时初值,控制脉冲宽度

MOV  DX,TIME     ; 音长初值,控制脉冲个数

IN  AL,61H      ; 读入61H端口

AND  AL,11111100B   ; 保持高6位不变

TRIG:

XOR  AL,2       ; D1位取反,交替出现1和0

OUT  61H,AL      ; D1位送61H端口

MOV  CX,F       ; 延时初值

DELAY:

LOOP DELAY       ; 延时控制,加大脉冲宽度

DEC  DX        ; 脉冲计数

JNE  TRIG       ; 控制音长

RET

SOUND   ENDP

CODE   ENDS

END  START

程序中读 61H 端口,保持高 6 位原来的值不变,这是因为高 6 位是控制其他设备的。使最低位为 0 是为了打开定时器门控。因为计算机运算速度很快,如果不进行延时,扬声器得到的脉冲频率过高,则人耳无法听到声音。所以程序中采用了循环作为延时措施,用来加大脉冲宽度以降低脉冲频率,从而控制声音的频率不至于太高。用 DX 寄存器的值控制脉冲个数,从而控制音长能达到一定时间。这样我们就能听到扬声器的发声。声音效果取决于机器的 CPU 速度,可以通过改变 CX 和 DX 寄存器的值来适应不同的机器。

(1)查询传送

通常外设速度总是低于 CPU 工作速度的,为防止数据的丢失,CPU 要不断查询外设的状态,只有当输入设备就绪或输出设备空闲时,才能进行数据传送;否则就等待。CPU 查询外设的状态也是通过执行输入指令读入该外设的端口(状态寄存器)数据,才能作出判断。这种先查询再传送的控制方式表明外设和 CPU 在时间上是串行工作的,CPU 花费大量的时间用于测试外设状态,等待与外设的同步,这是一种低效率的传送方式。当系统中有多个外设时,可以对每个设备轮流查询、轮流服务。

由图 2 可以看出,最先查询的设备,其工作优先级最高。改变查询顺序就改变了设备优先级。

轮流查询

图 2 轮流查询

(2)中断传送

查询传送中,CPU 为了不断测试外设状态而不能做任何其他事情,CPU 完全为外设服务。为了提高 CPU 的效率,采用中断方式,CPU 与外设并行工作。即 CPU 启动外设之后,不再等待外设工作的完成,而是执行其他程序。当外设需要和 CPU 进行数据传送时,主动向 CPU 发出中断请求,请求 CPU 为其服务,CPU 接到请求后,暂时中断当前程序的运行,转去执行处理相应的中断服务程序,完成所需的数据传送,当处理结束后,CPU 又返回到被中断的程序的断点处继续往下执行。这种方式避免了 CPU 反复查询外设的状态而浪费时间,可以使多台外设与 CPU 并行工作。

中断方式的一个典型例子是时钟中断,例如很多应用程序在运行阶段都有动态显示时间,如每隔一秒就显示一次当前时间。这里就把定时器作为一个外设,应用程序的开始设置定时器初值后,定时器就自行作减法计数,CPU 则继续执行自己的程序,此时定时器和 CPU 并行工作。当定时器计数为 0 时,就会发出一个中断信号,该中断信号就会被 CPU 及时捕获,于是 CPU 就暂停正在执行的程序,转而执行一段时钟中断处理程序,该中断处理程序再次设置定时器初值后,又返回到先前被暂停的应用程序继续执行。显然这里只能使用中断方式。

在很多集散型计算机生产过程多测点实时监控系统中,以中断和查询方式相结合,每隔一定时间或某个事件发生就启动后台程序,后台程序以查询方式进行多个测点的轮询访问,实现中心计算机与测点的数据传送。

(3)直接存储器传送(DMA)

前面介绍的数据传送方式都是使用程序进行外部设备与 CPU 之间的数据交换。而直接存储器传送方式是外部设备与主存储器之间直接进行数据交换而不通过 CPU。这种传送方式适用于高速 I/O 设备,如磁盘、模数转换器等设备。这种设备数据传输速度很快,例如硬盘的数据传输速率约为每秒 200 000 字节(随着硬盘数据密度的提高和转速的提高,数据传输速率越来越高),也就是说传输一个字节只需 5 微秒,如果采用指令一个字节一个字节地传输,则会造成数据的丢失。而 DMA 方式能使硬盘和主存储器进行成批数据的交换,每个字节一到达端口,就直接送到存储器,同样,接口和它的 DMA 控制器也能直接从存储器取出字节并把它送到硬盘。

DMA 控制器(8237A)主要包括控制寄存器、状态寄存器、地址寄存器、字节计数器。地址寄存器设置要传送的数据块首地址,字节计数器设置要传送的数据字节数,控制寄存器设置控制字,用以指出输入或输出,并启动 DMA 操作。系统执行 DMA 操作的过程如下。

① DMA 控制器向CPU发出 HOLD 信号,请求使用总线。

② CPU 发出 HOLD 信号给 DMA 控制器,DMA 控制器获得总线控制权。

③ DMA 控制器把地址寄存器中的存储器地址送到地址总线。

④ 传送一个字节数据。

⑤ 地址寄存器加 1,字节计数器减 1,若计数器的值不为 0,则转 ③ 继续传送下一字节。

⑥ 否则,本次数据交换完毕,DMA 控制器撤销总线请求信号,交还总线控制权。

请参阅

(完)

comments powered by Disqus