最近闲来无聊,在 上海图书馆 借了本《IBM-PC汇编语言程序设计》。没想,在看显示器访问的那章时。觉得作者讲得实在含糊,无法让人明白。后来,又借了本《80x86汇编语言程序设计》发现,这两本书在那一章节的内容几乎是一样,例子图片都一样。在我反复的摸索和在 上海科学技术情报研究所 里查看几天的资料后。终于模清了门路。当然,我也上网看了。没有相关的内容,也许是我没找到。所以,在这里献上我的成果希望有缘人能和我交流。
本文主要是介绍不用BIOS中断在VGA 640*480 16色模式下,对屏幕单个象素进行读写操作。我将用两段代码来说明如何操作,用于对各位处于迷茫的学者们一些提示。
在阅读本文前,我希望读者能够有一定的汇编基础,和对VGA显卡原理的基础知识(其实只要知道一些就可以了)。如果有空,可以在看本文之前阅读前面我借的两本书中的一本中,有关VGA显示卡的操作内容。
本文使用的例子,是用于NASM汇编器,读者可以从网上免费下载。我使用的软件,都可以从www.sf.net免费下载。
对VGA的写操作
首先是确定坐标位置,由于对内存的访问是一个字节,也就是 8 位二进制,而四个位面同一地址的字,构成了一个四位的颜色值。所以,我们需要确定在0a000h中的哪段地址进行操作。
b=x/8+y*80
既然知道如何计算所写的位置,我们就来写一段汇编代码。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;开始计算x/8 ;开始计算y*80 ;开始汇总计算 mov bl,al add dx,bx ;dx+bx mov word[x],dx ;恢复数据 x: dw 0 |
刚才的程序运行后,我们能通过写 0a000:x 的值来修改屏幕的象素。
然后,我们来看如何写。对于图形控制寄存器组,我这里不做介绍了。大家可以从书上看到,到处都是。
由于0a000:x中有八个象素的值,所以,为了能确定其中一个象素,我们必须使用刚才计算的y来将所给的数据进行偏移。
那么如果,偏移量是0说明是地址的开始位置,也就是10000000b。如果不是,那么如果是2,数据就是00100000b。所以,我们就可以知道如何在8个象素中确定其中一个象素。
照例,我们写一段代码
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov cx,word[y] ;将偏移量入cx ;恢复现场 b: db 0 ;程序运行完成,b中的内容为写入的数据位置。 |
最后,我们要来完成写入工作了。
对于写,我个人觉得书上说的很不清楚,因为,位屏蔽寄存器是需要读锁存的。然而,前面对VGA的工作原理没有详细的介绍。造成后面对位屏蔽的错误理解。
由于锁存是需要读入的,所以,在每次写操作前要使用位屏蔽必须先读一次。将数据写入锁存以便后面使用。
对于颜色的设置,我们可以通过 设置重置寄存器 和 设置重置允许寄存器 来完成。
设置重置寄存器 索引 0h
位: 0 写入位面0的数据
位: 1 写入位面1的数据
位: 2 写入位面2的数据
位: 3 写入位面3的数据
位 4~7 保留
设置重置允许寄存器 索引 1h
位: 0 位面0设置重置允许
位: 1 位面1设置重置允许
位: 2 位面2设置重置允许
位: 3 位面3设置重置允许
位:4~7 保留
下面,我们就来看看写的例子。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;还是接着上面的例子。 push dx ;保存现场dx数据 push ax ;保存用户输入的颜色信息 ;对图形控制器寄存器操作 mov dx,3cfh ;设置重置允许寄存器 mov dx,3cfh ;设重置寄存器 mov dx,3cfh ;设置数据循环位移寄存器 mov dx,3cfh ;设置位屏蔽寄存器 mov dx,3cfh ;设置数据段和初始参数 ;因为我们只是让VGA读一次现存。所以,我们就听天由命的读一次内存吧,反正我们也不用这个参数。 mov dx,3cfh mov dx,3cfh mov dx,3cfh mov dx,3cfh ;然后我们就来进行写了。 ;恢复现场数据 ;到这里,所有的写操作算是完成了。 |
下面,我就把完成的子程序代码贴出来。其实,就是上面三组代码的整合。(听起来像IBM说的“整合”)。不过这里注释就不加了,因为上面都有了。
下面这段代码在Nasm下编译成功,并且运行良好。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov ax,cx pop ax mov ax,word[x] mov word[x],dx mov al,ah ;S1 End ;S2 Start mov cx,word[y] pop cx ;S2 End ;S3 Start push dx mov dx,3ceh mov dx,3cfh mov dx,3ceh mov dx,3cfh mov dx,3ceh mov dx,3cfh mov dx,3ceh mov dx,3cfh mov dx,3ceh mov dx,3cfh mov ax,0a000h mov bx,word[x] mov dx,3ceh mov dx,3cfh mov dx,3cfh mov dx,3cfh mov dx,3cfh pop ax ;S3 End ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
STUDIO软件开发组(SDT)
STUDIO Development Team
北斗星君(黄庠魁)
2005年1月