ITEEDU

6.4端口编程

6.4导航:第一页 第二页 第三页

 可移植性历来是汇编语言所面临的最为严重的问题之一,特别是编程控制显示卡上的端口,这个问题更为突出。原因在于我们现在大量使用的VGA/Super VGA卡没能做到在端口一级兼容早期的CGA卡。这不能不说是一种遗憾,要知道这些卡几乎都做到了在显示缓冲存储器一级兼容CGA卡,只差一小步。因此,这一节将只准备讨论那些适用于各种显示卡的端口寄存器,给出的程序可以在大多数显示卡上运行。首先我们要解决的第一个问题是DX寄存器在端口操作中的应用。

我在前面曾经提到过DX寄存器在端口输入与输出中有特殊的用途,而且在讨论发声程序时也说到过指令"IN AL,??H"的形式只能在端口号小于0FFH时应用,但是显示卡上的端口号都大于0FFH,如何才能访问到这些端口呢?

在给出具体的方法之前,我们还需复习一下有关寻址方式的知识。当我们从内存中取得数据时,我们可以采用直接寻址方式和寄存器间接寻址方式,以MOV指令为例,如果我们从DS:1234处读取一字节数据到累加器,我们可以使用两种方法编制程序:MOV AL,DS:[1234H]或MOV BX,1234H;MOV AL,[BX]。第一种方法就是直接寻址方式,第二种方法就是寄存器间接寻址方式。事实上,端口的访问和内存访问有很多相似的地方,象"IN AL,61H"这样的用法其实就是对端口的直接寻址,那么端口的间接寻址又是什么情形呢?形式与访问内存差不多: MOV DX,端口号 IN 累加器,DX;(或OUT DX,累加器)

当然,区别还是有的:首先,我们只能使用DX寄存器做间接寻址;其次,访问端口无需采用"[DX]"的形式。在后面给出的程序例中你可以看到这种方法的具体应用。

知道如何访问端口,这只是一个开始,我们第二步需要了解的就是显示卡上的端口寄存器的结构。显示卡上的寄存器数量很多,如果给每个寄存器都分配一个端口号那将耗用很多的端口地址资源。而且给设计程序带来不便。所以几乎所有的显示卡都采用了"寄存器堆"的结构。

所谓寄存器堆,其实就是将一些功能相关的寄存器组成一组,分配一个端口号,所有寄存器都从这一个端口输入输出。大家可能会联想起我们在前面讲解定时器时曾经说过,给定时器设定"N"值时要把16位的数据分成两次从同一端口"42H"送进定时器。注意这和现在要讲的知识并不一样。这是因为既然"一堆"寄存器只有一个端口传输数据,那么我们要访问其中一个寄存器就必须有办法"指定"要访问的对象。所以一个寄存器堆实际分配了两个端口,第一个用于指定要访问的寄存器,第二个用于传输数据。

习惯上通常将第一个端口称为"索引"端口,将第二个端口称为"数据"端口。一般情况下索引端口地址与数据端口地址是相临的,如显示卡上有一个被称为CRTC(CRT Controler)的寄存器堆,专门用于控制送到显示器的各种信号,系统分配给这个寄存器堆的两个端口地址是3D4H和3D5H,其中3D4H是"索引"端口,3D5H是"数据"端口。如果程序要访问CRTC的第10个寄存器,那么首先要向端口3D4H送出寄存器号10,此时CRTC的第10个寄存器就和端口3D5H相连通,这时候再用"IN"或"OUT"对端口3D5H进行操作,就可以取得CRTC10号寄存器的数据或将数据送入CRTC10号寄存器中。相应的程序如下:

MOV DX,3D4H	;准备访问"索引"端口3D4H	
MOV AL,10		;选择CRTC10号寄存器	
OUT DX,AL		;输出寄存器号	
MOV DX,3D5H	;准备访问"数据"端口3D5H	
IN AL,DX 		;读取CRTC10号寄存器的值 	

 了解了显示卡上的寄存器结构,第三步就是要详细了解寄存器堆中每个成员的作用了。表6-2列出了CGA卡上CRTC寄存器堆中所有寄存器的功能,共有18个寄存器:

下面对这些寄存器作一些详细的说明:

(1)CRTC0-CRTC3称为水平寄存器,用来控制显示器水平方向的显示特性,比如每行字符数,每个字符的宽度等。
(2)CRTC4-CRTC9称为垂直寄存器,用来控制显示器垂直方向的显示特性,比如全屏显示的字符行数,每个字符占据的扫描线数等。
(3)CRTC16-CRTC17,这两个寄存器用来控制光笔。
(4)CRTC10-CRTC15,这六个寄存器是我们重点要讨论的,通过这六个寄存器,我们可以详细了解BIOS功能调用的执行情况。

表6-2 CTRC寄存器的功能
寄存器
编 号
寄存器名称 寄存器
类 型
参数单位 设定值
40x25 80x25 图形模式
00 水平扫描总时间 只写 字符 38 71 38
01 每行字符数 只写 字符 28 50 28
02 水平同步位置 只写 字符 2D 5A 2D
03 水平同步宽度 只写 字符 0A 0A 0A
04 垂直扫描总时间 只写 字符行 1F 1F 7F
05 垂直总调节 只写 扫描线 06 06 06
06 每帧显示行数 只写 字符行 19 19 64
07 垂直同步位置 只写 字符行 1C 1C 70
08 隔行扫描方式 只写 —— 02 02 02
09 最大扫描线地址 只写 扫描线 07 07 01
10 光标起始 只写 扫描线 06 06 06
11 光标结束 只写 扫描线 00 00 00
12 起始地址(高位) 只写 —— 00 00 00
13 起始地址(低位) 只写 —— XX XX XX
14 光标位置(高位) 读写 —— XX XX XX
15 光标位置(低位) 读写 —— XX XX XX
16 光笔位置(高位) 只读 —— XX XX XX
17 光笔位置(低位) 只读 —— XX XX XX