ITEEDU

另一个较为有用的功能是取得光标所在位置的字符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与文字显示的关系。