-158- | PC机汇编语言实战精解 | ![]() |
|||||||||||||||||||
C:\ASM\>DEBUG[Enter] -a100[Enter] |
|||||||||||||||||||||
1028:0100 1028:0103 1028:0105 1028:0107 1028:010A 1028:010C 1028:010D 1028:0110 1028:0112 1028:0114 1028:0115 1028:0117 1028:0119 1028:011A 1028:011C |
MOV MOV INT CMP JZ INC MOV MOV MOV OUT MOV MOV OUT JMP INT |
BX,0000 AH,00 16 AH,01 011C BX DX,03D4 AL,0E AH,BH DX,AX AL,0F AH,BL DX,AX 0103 20 |
;光标地址清0 ;等待键盘输入 ;是"ESC"键吗? ;是"ESC"则转011C结束 ;光标地址加1 ;DX指向索引寄存器 ;CRTC14寄存器的索引号送AL ;光标地址高字节送AH ;将光标地址高字节送CRTC14 ;CRTC15寄存器的索引号送AL ;光标地址低字节送AH ;将光标地址低字节送CRTC15 ;转0103继续 ;结束程序 |
||||||||||||||||||
运行这个程序,按下任一键后光标跑到第一行第二列上,此后无论按下哪个键光标都会移动到下一个位置,直至按下Esc后程序结束。这个程序看上去很简单,但它又包含了两个新的知识点: (1)当我们使用16H中断的0号功能取得按键后我们并未跟据AL寄存器中的ASCII码来判断按下何键,而采用了AH中的返回数据; (2)在向端口输出数据时,我们也没有采用先由索引端口送出寄存器号,后由数据端口送出数据的标准形式,而是将寄存器号放入AL,将数据放入AH,然后向端口3D4H输出了一个字。这两个新知识点都与AH寄存器有关,我们先来讨论第二点。 还记得我们前面讨论的关于"PTR"操作符的问题吗?访问存储器时我们可以用这个操作符指定访问内存中的一个字节或一个字,其实访问端口也可以指定位宽,我们使用AL寄存器访问端口时只能输出或输入一个字节数据,如果使用AX寄存器访问端口就能输出或输入一个字的数据。例如上面程序中的指令"OUT DX,AX"就是向端口3D4H输出一个字数据。那么这一个字数据究竟送到哪儿去了? 从上面这个程序执行的结果来看我们可以猜测出AL寄存器中的数据应该送至端口3D4H,而AH中的数据应该送至端口3D5H,这才可能出现光标移动的结果。这个猜测的确是对的,输出数据的低字节送到了DX寄存器指定的端口,而高字节送到了端口DX+1处。这一点和访问内存时的情况一样,指令"MOV [BX],AX"执行时同样会将AL中的数据送至[BX]处,而将AH中的数据送至[BX+1]处。我们前面曾经说过端口也是一些存储单元,它具有内部寄存器和存储器双重的特性,学习到这里你应该对这个说法有了充分的理解。不过有一点特殊的地方我必须说明,那就是16位数据只能从偶数地址端口输出或输入,而不能从奇数地址端口输出或输入字数据,这一点是和访问内存不一样的。 说了这么多的东西,这一节的内容到此就可以结束了。一般来说我们不提倡通过端口控制显示卡的工作,因为这会使程序的可移植性变坏。这是有先例的,CCDOS2.1版就是因为这个原因无法在EGA/VGA卡上运行。所以除非特殊需要,我们应尽量使用BIOS完成对显示卡的控制,使用直接写屏的方法完成显示操作,这样就可以兼顾效率与可移植性两个方面。 |
|||||||||||||||||||||
Copyright © 2004-2015 Reanimator | www.cookmoon.org |