第 9章 I/O程序设计
9.1 I/O操作
9.2 直接传送方式
9.3 中断传送方式
9.4 DMA传送方式
9.5 文件 I/O
9.1 I/O操作
CPU与外设之间的信息交换,是通过接口电路中的 I/O端口进行的。
CPU通过 IN/OUT指令可以对端口进行读、
写操作。
9.1.1 I/O端口及其分配计算机由 CPU,内存储器和外部设备组成
内存与 CPU可直接进行数据交换
外设与 CPU通过 I/O接口电路来连接
输入 /输出是相对于 CPU而言
输入操作:输入设备把信息送入接口,由 CPU从接口电路中取得接口中的信息。
输出操作,CPU将信息传送给接口电路,再由接口电路传送到外设。
I/O接口包含 3种类型的信息:
( 1) 来自外设的数据或要送往外设的数据,分别保存在数据输入寄存器和数据输出寄存器中;
( 2) 用来存放外设或者 I/O接口部件本身的状态,
保存在状态寄存器中;
( 3) 用来存放 CPU发出的命令,以便控制外设和接口的动作,保存在控制寄存器中 。
端口和端口地址
端口,I/O接口电路中能被 CPU直接访问的寄存器称为端口
端口地址:端口的地址
CPU访问 I/O端口的方式:
统一编址方式(存储器映射方式 )
独立编址方式( I/O映射方式 )
统一编址和独立编址
统一编址
端口地址与存储器地址统一编址
从存储空间中划出一部分地址空间分配给 I/O设备
CPU不需要使用专门的 I/O指令来访问 I/O端口
一个地址要么是内存单元,要么是 I/O端口
独立编址
I/O端口地址与存储器地址分别进行独立的编址
内存地址空间和 I/O地址空间相互独立
CPU必须使用专门的 I/O指令来访问 I/O端口
内存操作指令使用内存地址,I/O指令使用 I/O地址
9.1.2 I/O指令
I/O指令 包括:
IN指令
OUT指令
INS指令
OUTS指令
1,IN指令格式,IN {AL∣AX∣EAX},{端口地址 ∣ DX}
功能:将 I/O端口中的信息读入到累加器中。
累加器为 AL时,从指定端口中读出 1个字节送给 AL;
累加器为 AX时,从指定端口中读出 1个字节送给 AL,
从下一端口地址中读出 1个字节送给 AH。
累加器为 EAX时,连续读出从指定地址开始的 4个端口中的内容,分别送给 AL,AH和 EAX的第 23~16位、
EAX的第 31~24位。
当端口号大于等于 256时,先把端口号放到 DX寄存器中。当端口号小于 256时,在 IN指令中直接给出端口号。
IN指令举例例 1:从端口地址为 61H的端口上读取一个字节
IN AL,61H
例 2:从端口地址为 379H的端口上读取一个字节
MOV DX,379H
IN AL,DX
例 3:从端口地址为 0E000H,0E001H的端口上读取一个字
MOV DX,0E000H
IN AX,DX
2,OUT指令格式,OUT {端口地址 ∣ DX},{AL∣AX∣EAX}
功能:将累加器中的信息输出到 I/O端口 。
累加器为 AL时,AL中的内容输出到指定端口中;
累加器为 AX时,AL中的内容输出到指定端口中,AH
中的内容输出到下一端口中;
累加器为 EAX时,AL,AH,EAX的 23~16位,EAX的
31~24位的内容输出到从指定地址开始的 4个端口中 。
当端口号大于等于 256时,必须先把端口号放到 DX
寄存器中 。 当端口号小于 256时,在 OUT指令中可以直接给出端口号 。
OUT指令举例例 1:将 AL中的内容输出到 61H端口:
OUT 61H,AL
例 2:将 AL中的内容输出到 37Ah端口:
MOV DX,37AH
OUT DX,AL
例 3:将 AL和 AH中的内容输出到 3CEH,3CFH端口:
MOV DX,3CEH
OUT DX,AX
3,INS指令格式,INSB/INSW/INSD
功能:将 I/O端口中的信息读入到 ES:[EDI]指向的内存单元中 。
使用 INSB时,从端口号为 DX的端口中读出 1个字节送给 ES:[EDI]单元 。
使用 INSW时,从端口号为 DX和 DX+1的端口中分别读出 1个字节送给 ES:[EDI],ES:[EDI+1]单元 。
使用 INSD时,从端口号为 DX,DX+1,DX+2,DX+3的端口中分别读出 1 个 字 节 送 给 ES:[EDI],
ES:[EDI+1],ES:[EDI+2],ES:[EDI+3]单元 。
INS指令举例从 170H端口连续读取 512次,将读取到的信息放在 Buffer数组中
buffer BYTE 512 DUP (?)
MOV DX,170H
MOV ECX,512
LEA EDI,Buffer
CLD
REP insb
4,OUTS指令格式,OUTSB/OUTSW/OUTSD
功能:将 DS:[ESI]指向的内存单元中的信息输出到 I/O端口中 。
使用 OUTSB时,DS:[ESI]内存单元中的信息输出到端口号为 DX的端口中;
使用 OUTSW时,DS:[ESI],DS:[ESI+1]内存单元中的信息分别输出到端口号为 DX,DX+1的两个端口中;
用 OUTSD 时,DS:[ESI],DS:[ESI+1],DS:[ESI+2],
DS:[ESI+3]内存单元中的信息分别输出到端口号为
DX,DX+1,DX+2,DX+34个端口中 。
OUTS指令举例程序连续输出 512次,将 Buffer中的信息不断输出到 170H端口
MOV DX,170H
MOV ECX,512
LEA ESI,Buffer
CLD
REP outsb
9.1.3 保护模式下 I/O指令的限制
不允许应用程序使用 I/O指令
操作系统及其驱动程序可以执行 I/O指令
9.2 直接传送方式外设数据传送的控制方式通常有三种:
直接传送方式,又分为
无条件传送方式
查询方式
中断传送方式
DMA传送方式
9.2.1 CMOS数据的读取
实时钟信息保存在 CMOS RAM中
CMOS RAM是一种存储器,对它的访问必须通过 I/O接口电路用 I/O指令来完成举例:读取实时钟 cmosram.asm
9.2.2 扬声器发声程序
9.2.3 串行 I/O
串行接口是微机应用系统常用的接口,
也被称做 COM口和 COM口有关的几个主要端口:
发送保持寄存器,简称为 THR ( 输出端口)
接收缓冲寄存器,简称为 RBR ( 输入端口)
线路状态寄存器,简称为 LSR ( 输入端口)
9.2.4 并行 I/O
并口主要用来连接打印机,被称做 LPT。 并口有 3个端口:
数据端口(地址为 378H )
状态端口(地址为 379H )
CPU读取这个端口来获得打印机的状态信息
控制端口(地址为 37AH )
CPU通过这个端口来控制打印机打印机状态端口的格式打印机控制端口的格式
9.3 中断传送方式
直接传送方式,CPU要不断地查询外设的状态,当外设未准备好时,CPU就只能循环等待,CPU的效率很低。
采用中断方式,系统中采用含有中断功能的接口电路,用来产生中断请求信号,
在外设状态变化后通知 CPU。 可以提高
CPU的工作效率。
9.3.1 基本原理
外设通过接口电路向 CPU发出中断请求信号
CPU暂停执行当前正在执行的程序,转入执行相应的中断服务程序
在中断服务程序中,执行输入 /输出操作
返回继续执行原来被中断的程序
CPU避免了把时间耗费在等待、查询状态信号的操作上,因此效率得以大大地提高。
中断传送方式的工作原理 图
1.中断源键盘控制器能够产生中断信号,称之为一个中断源。实时时钟、串口、并口等也是中断源。
系统依赖可编程中断控制器 8259来管理各个中断源。 PC机最多支持 15个中断源,当同时有多个中断源发出中断信号时,8259处理优先级最高的那一个中断源。
2.中断屏蔽标志寄存器 EFLAGS中的 IF标志决定是否响应 INTR
( 可屏蔽中断请求 ) 。
8259内部也有一个中断屏蔽寄存器 。
每一个中断源对应于其中的一个二进制位 。
当某个二进制位的值为 1时,表示其对应的中断源被屏蔽 。
3.中断类型号与中断向量外部硬件在通过 INTR发出中断请求信号后,CPU
在响应中断请求时,再从外部硬件读出一个 8位的中断类型号。
中断类型号的范围是 00H~ FFH,用来区分外部中断的来源。
9.3.2 中断服务程序中断服务程序处理与中断相关的事务,控制外设进行 I/O操作,包括如下步骤:
保存寄存器内容
进行与该中断源有关的 I/O操作
发送中断结束命令给 8259
恢复寄存器内容
执行 IRETD指令返回被中断的程序
1,IRETD指令格式,IRETD
功能:中断服务程序执行完毕后,执行 IRETD指令从堆栈中取出标志寄存器,CS和 EIP( 以及
SS,ESP),再返回被中断的程序 。
在进入中断服务程序时,CPU将标志寄存器,CS和
EIP压栈
中断服务程序的最后一条指令是 IRETD,它从堆栈中取出 CS和 EIP并恢复标志寄存器的内容 。
2,IRET指令格式,IRET
功能:其功能相当于 IRETD。
一般将 16位实模式代码中的中断返回指令写做
IRET,而将 32位保护模式代码中的中断返回指令写做 IRETD。
3,CLI指令格式,CLI
功能:将 EFLAGS中的 IF标志位清零 。
IF等于 0时,CPU不响应外部中断 。
4,STI指令格式,STI
功能:将 EFLAGS中的 IF标志位置 1。
IF等于 1时,CPU响应外部中断 。
9.4 DMA传送方式当 I/O和内存之间需要进行大量的快速传送时,
如果仍然采用直接传送方式和中断传送方式,会极大地限制 I/O的传送速度,占用 CPU的执行周期。
为了提高数据传送的速率,降低 CPU负荷,微机系统实现了 DMA数据传送方式。在一定时间段内,
由 DMA控制器取代 CPU,获得总线控制权,来实现
I/O和内存之间的快速传送。
9.4.1 DMA传送的过程
DMA数据传送的工作过程
( 1) 外设向 DMAC发出 DMA传送请求 。
( 2) DMAC通过 HOLD信号向 CPU提出 DMA请求 。
( 3) CPU在完成当前总线操作后会立即对 DMA请求做出响应 。
首先,CPU将控制总线,数据总线和地址总线浮空,
即暂时脱离这些总线,放弃对这些总线的控制权;
然后,CPU将有效的 HLDA信号传送给 DMAC上,通知
DMAC可以获得总线的控制权 。
DMA数据传送的工作过程(续)
( 4) DMAC收到 HLDA信号,并且总线处于浮空状态后,接管系统总线的控制权,并向外设送出 DMA的应答信号 。
( 5) 由 DMAC送出地址信号和控制信号,实现 I/O和内存之间大量数据的快速传送 。 每传送一次数据,DMAC都会自动地调整内存地址,在下一次传送时使用不同的内存地址 。
( 6) DMAC将数据传送完成之后,向 CPU发 HOLD信号,撤销 DMA请求 。
( 7) CPU收到 HOLD信号,一方面使 HLDA无效,另一方面又重新开始控制总线,实现正常取指令,分析指令,
执行指令的操作 。
9.4.2 软盘控制器与 DMA
PC机软盘上的数据是通过 DMA传送到内存的。
软盘控制器连接到 8237DMA的通道 2。
9.5 文件 I/O
内存只是一种,临时性,的存储媒介,程序运行结束后,内存被释放,保存在内存中的数据也随之丢失 。
如果需要永久地保存程序运行所需的原始数据或运行产生的结果,就必须以文件的形式存储到外部存储介质上,如软盘、硬盘,USB盘 等。
9.5.1 文件
1.文件与文件名文件是指存放在外部存储介质上的数据集合 。
文件名格式:主文件名 [.扩展名 ]
扩展名也称为后缀,可决定文件的类型如,doc,.txt,.asm等 。
文件(续)
2,文件分类几种常见的分类方法:
根据文件的内容,可分为程序文件和数据文件;
程序文件又可分为源文件,目标文件和可执行文件 。
根据文件的组织形式,可分为顺序存取文件和随机存取文件 ;
根据文件的存储格式,可分为 ASCII码文件和二进制文件 。
文件(续)
3,对文件的基本操作基本操作包括:
打开文件
读文件
写文件
关闭文件文件(续)
4,文件类型结构 FILE
系统为每个打开的文件在内存中开辟一个区域,
用于存放文件的有关信息,这些信息保存在一个结构类型变量中,名为 FILE。
文件(续)
5,缓冲文件系统缓冲文件系统是指系统自动地在内存中为每个正在使用的文件开辟一个缓冲区 。
从内存向文件写数据时,先将数据复制到缓冲区中 。
待缓冲区填满后,再将缓冲区的内容输出到文件中 。
从文件向内存读数据时,系统首先将大量数据读入到缓冲区中,再从缓冲区中将数据送到程序数据区 。
9.5.2 文件操作的基本函数
C语言提供了一些库函数,用于对文件的打开、读取、写入、关闭等 ;
书中 307页列出了常用的一些库函数 。
1.系统定义的 3个文件
stdin—— 标准输入文件,即终端输入,
一般为键盘;
stdout—— 标准输出文件,即终端输出,
一般为显示器;
stderr—— 标准错误文件,一般为显示器 ;
2.文件的打开模式文件的打开模式(续)
在编程时,在打开方式中选取一种,再从文件类型中选取一种,如:
fopen ("tmpfile","wb");
另外:
对二进制文件的读写操作,多使用 fread和
fwrite
对文本文件的操作,多采用 fgets和 fputs
3.文件指针每一个被打开的文件都有一个读写位置指针,指向当前的读写位置 。
每次读写一个 ( 或一组 ) 数据后,系统自动将位置指针移动到下一个读写位置上 。
文件指针是一个长整数,表示当前读写位置在整个文件中的偏移 。
文件指针(续)
设置文件指针的函数如下:
int fseek(FILE *fp,long pos,int where);
where指出本次操作的参照点
pos表示位移量
9.5.3 文件处理实例例 1.在文本文件中查找字符串
grepstr.c
grepstr.asm
例 2:对文件内容加密 /解密
crypt.asm