另一个较为有用的功能是取得光标所在位置的字符ASCII码和属性的功能:
功能号:08H
用 途:取光标位置的字符及属性
参 数:BH=显示页号
调 用:INT 10H
返 回:AL=ASCII码
AH=属性字节
注意这个功能调用只在文本方式下工作,图形方式下无效。下面这个程序演示了这个功能调用的应用:
data segment assume ds:data keymsg db 'I--cursor UP',0dh,0ah ;定义一组说明性的文字 db 'J--cursor LEFT',0dh,0ah db 'K--cursor RIGHT',0dh,0ah db 'M--cursor DOWN',0dh,0ah db 'Otherkey---EXIT to DOS',0dh,0ah,'$' current db ? ;存放光标当前的位置 db ? data ends code segment assume cs:code main proc far mov ax,data ;初始化DS寄存器 mov ds,ax mov dx,offset keymsg ;输出字符串KEYMSG mov ah,9 int 21h mov ah,3 ;利用10H中断的03功能 int 10h ;取得当前光标位置 mov current,dh ;保存光标当前位置 mov byte ptr current+1,dl get_key: mov ah,0 ;等待键盘输入 int 16h or al,20h ;将输入的字符转换成小写字母 cmp al,'i' ;输入的是'i'键吗? jnz is_j ;不是'i'键,转IS_J继续 dec byte ptr current ;光标所在行号减1 jns mov_cur ;如果光标行号仍不小于0,则移动光标 mov byte ptr current,24 ;若光标行号小于0,将其移动到屏幕底部 jmp mov_cur ;转MOV_CUR移动光标 is_j: cmp al,'j' ;输入的是'j'键吗? jnz is_k ;不是'j'键,转IS_K继续 dec byte ptr current+1 ;光标所在列号减1 jns mov_cur ;若光标列号不小于0,则移动光标 mov byte ptr current+1,79 ;若光标列号小于0,将其移动至屏幕右端 jmp mov_cur ;转MOV_CUR移动光标 is_k: cmp al,'k' ;输入的是'k'键吗? jnz is_m ;不是'k'键,转IS_M继续 inc byte ptr current+1 ;光标所在列号加1 cmp byte ptr current+1,79 ;光标列号大于79吗? jb mov_cur ;小于79则移动光标 mov byte ptr current+1,0 ;大于79则将光标移动到屏幕最左端 jmp mov_cur ;转MOV_CUR移动光标 is_m: cmp al,'m' ;输入的是'm'键吗? jnz exit ;不是'm'键,转EXIT结束 inc byte ptr current ;光标所在行号加1 cmp byte ptr current,24 ;光标行号大于24吗? jb mov_cur ;小于24则移动光标 mov byte ptr current,0 ;大于24则将光标移动到屏幕顶部 mov_cur: call move_cur ;调用MOVE_CUR子过程移动光标 call change_attr ;调用CHANGE_ATTR子过程改变字符属性 jmp get_key ;跳至GET_KEY继续等待键盘输入 exit: mov ah,4ch ;结束进程 int 21h main endp move_cur proc near ;移动光标子过程 push dx ;保存所用的寄存器 push ax mov ah,02 ;选择10H中断的02功能 mov bh,0 ;显示页号置入BH寄存器 mov dh,byte ptr current ;光标行号送入DH寄存器 mov dl,byte ptr current+1 ;光标列号送入DL寄存器 int 10h ;移动光标位置 pop ax ;恢复寄存器 pop dx ret ;返回主过程 move_cur endp change_attr proc near ;改变字符属性子过程 push ax ;保存所用的寄存器 push cx mov ah,8 ;选择10H中断的08功能 mov bh,0 ;显示页号送入BH寄存器 int 10h ;取得光标指向字符的ASCII码及属性 cmp al,30h ;这个字符是数字吗? jb retu ;不是数字则返回 cmp al,39h ja retu mov bl,ah ;取得的字符属性送入BL寄存器 or bl,80h ;将属性改为闪烁显示 mov cx,1 ;显示一个字符 mov ah,9 ;利用10H中断的09功能 int 10h ;重新显示字符及新的属性 retu: pop cx ;恢复寄存器 pop ax ret ;返回 change_attr endp code ends end main
程序的"企划"很简单,运行这个程序后我们可以用"I,J,K,M"四个键移动光标,如果将光标移动到"数字"的下面,则让这个数字变为"闪烁"显示,光标移动到字母或其它符号下面显示效果无变化。
这个程序要完成这样一些事情:进入程序后首先要取得当前光标位置并保存到数据段中;然后要取得按键并判断是何按键;第三要根据按键情况在新位置设定光标;第四要取得光标所在新位置的字符并判断这个字符是否为数字;第五要重新设置数字的属性字节并将具有新属性的数字在光标位置显示出来。五项重点工作要使用五种BIOS功能调用,其中10H中断的08号功能就是我们重点要掌握的。
另外两个有关字符的功能调用相对来说不太重要,它们是10H中断的04H和0AH功能调用。04H功能于读取光笔位置,光笔也是一种输入设备,不过在我们的PC电脑中应用得很少;0AH功能用于在屏幕当前光标位置处写字符,但这个功能既不能显示有属性的字符,也不能自动处理光标后移,所以应用得也很少。这两个功能我们也就不再多说了。
这一节的内容还是相当丰富的,我们详细讨论了应用在字符模式下的几个功能调用,这些功能都是由BIOS为我们提供的。而DOS的21H中断也为我们提供了一些用于输出字符的功能,不过这些功能调用一般都不能直接处理属性,所以我也不准备详细讨论它们,如果你需要使用这些功能,可以查阅本书的附录。这一节的研究到此结束,下一节我们将讨论Video RAM与文字显示的关系。