BIOS功能(子程序)调用通过软中断指令INT实现,其格式为:INT n
n的取值范围是0~255,每个n对应一段子程序。与一般子程序调用一样,在BIOS功能调用前也要设入口参数,功能调用也会返回参数(不是所有的功能都有参数返回)。本节将介绍几个最常用的BIOS调用。
(1)INT 16H键盘输入。
①AH=0:从键盘读入一键。
返回参数:AL=ASCII码,AH=扫描码。
功能:从键盘读入一个键后返回,按键不显示在屏幕上。对于无相应ASCII码的键,如功能键等,AL返回0。此时,应再次以AH=0调用,AL中返回该键的扩展编码(大多数情况下与扫描码相同)。
②AH=1:判断是否有键盘输入。
返回参数:若ZF=0,则有键盘输入,AL=ASCII码,AH=扫描码;若ZF=1,键盘无输入。
(2)INT 33H鼠标功能。
INT 33H用于提供鼠标的相关信息,如鼠标的当前位置、最近一次的按键和移动速度、鼠标的按下和释放状态等。
注意:INT 33H的功能号应该送AX而不是常用的AH。
下面介绍几种最常用的鼠标功能。
①AX=1:显示鼠标指针。
使鼠标指针显示在屏幕上,无返回参数。
②AX=2:隐藏鼠标指针。
无返回参数,执行后鼠标指针不可见,但是鼠标的位置仍然被记录。
③AX=3:获取鼠标位置和状态。
返回参数:BX=鼠标状态,其中D0=1表示左键被按下,D1=1表示右键被按下,D2=1表示中键被按下;CX=鼠标当前的X坐标(水平位置,以像素为单位);DX=鼠标当前的Y坐标(垂直位置,以像素为单位)。
在MS-DOS下,一个字符的宽和高都是8个像素,因此像素的坐标除以8就转换成字符的坐标。
④AX=4:设置鼠标的位置。
入口参数:CX=X坐标(水平位置,以像素为单位);DX=Y坐标(垂直位置,以像素为单位),无返回参数。
如果想把鼠标定位于第5行第6列字符处,设置CX=5×8=40,DX=6×8=48。例如,跟踪鼠标,在屏幕的右上角显示鼠标的即时坐标。
INCLUDE YLIB.H.MODEI SMALI.CODE
MAIN PROC
CALL SHOWMOUSE
AGAIN:
CALL SETXY ; 设置光标位置(1行60列)
CALL GETPOSITION ; 获得鼠标的当前位置
CALL SHOWPOSITIoN ; 在光标处显示鼠标位置行:列
MOV CX,2000H
LOOP $ ; 延时
JMP AGAIN ; 重复上面过程,直到按下Ctrl+Break组合键
MAIN ENDP
SHOWMOUSE PROC ; 子程序SHOWMOUSE,使鼠标指针可见
PUSH AX
MOV AX,1
INT 33H
POP AX
RET
SHOWMOUSE ENDP
SETXY PROC
MOV AH,2
MOV DH,1
MOV DI,60
MOV BH,0
INT 10H ; 设置光标位置为1行60列
RET
SETXY ENDP
GETPOSITION PROC ; 子程序GETPOSITION
MOV AX,3
INT 33H ; 得到鼠标当前位置在CX/DX中
RET
GETPOSITION ENDP
SHOWPOSITION PROC ; 子程序SHOWPOSITION
PUSH CX
MOV AX,DX
MOV DX,0FFFFH
CALL WRITEINT ; 显示鼠标当前的行号(垂直位置)
MOV DI,':'
MOV AH,02H ; 输出一个冒号
INT 21H
POP AX
MOV DX, 0FFFFH
CALL WRITEINT ; 显示鼠标当前的列号(水平位置)
RET
SHOWPOSITION ENDP
END MAIN
与BIOS功能调用相比,DOS功能调用功能更强大,使用更方便。但是,DOS功能调用没有重入功能,也就是不能递归调用,所以不能在中断服务程序内使用。
MS-DOS负责文件管理、设备管理、内存管理和一些辅助功能,功能十分强大。DOS功能调用使用INT 21H指令,AH中存放功能号,表示需要完成的功能。每个功能调用都规定了使用的入口参数和存放该参数的寄存器,调用产生的返回参数也通过寄存器传递。
MS-DOS不仅为用户提供了许多可直接使用的命令,而且还为汇编语言的用户提供了几十个内部子程序,供程序员直接调用。为方便调用,每个子程序对应有一个调用功能号。
系统功能调用中的几十个子程序已成为汇编语言程序员的重要工具,程序员不必了解所使用设备的物理特性、接口方式和内存分配,不必编写复杂的控制程序,调用它们时采用统一的格式,只需要做到:
(1)所需的入口参数送指定单元(通常是指定的寄存器)。
(2)将子程序功能号送入AH寄存器中。
(3)执行INT 21H指令,实现DOS功能调用。
DOS根据功能号携带入口参数转入相应的子程序执行,运行的结果由出口参数带出,一般也在某些寄存器中。
(1)字符输入功能调用(1号)。它没有入口参数,执行1号系统功能调用时,系统等待键盘输入,当按下任何一个键时,系统先检查是否为Ctrl+Break组合键,如果是则退出运行的程序,否则将输入字符的ASCII码送入AL寄存器中,并在屏幕上显示该字符,程序继续向下执行。1号系统功能调用的格式如下:
MOV AH,1
INT 21H
(2)字符输出功能调用(2号)。2号调用的功能是将DI寄存器中的字符送屏幕上输出显示。2号调用时要求将显示字符的ASCII码(入口参数)事先送入DI中。
(3)字符串输入功能调用(10号)。10号系统功能调用是将键盘上输入的字符串写到内存缓冲区中,因此要求事先在内存储器中定义一个输入缓冲区,缓冲区的第一个字节单元给出该缓冲器能容纳的字符个数,第二字节单元留给系统填入实际输入的字符个数,从第三字节单元开始用来存放输入的字符串。调用前,必须使DS:DX指向该缓冲区。执行10号功能调用时,系统等待从键盘上输入字符,输入Enter键表示字符串输入结束。如果实际输入的字符数不足以填满缓冲区,则剩余的字节存储单元填0,如果实际输入的字符数超过定义的缓冲区容量,则超出的字符被丢弃,并且响铃警告。
(4)字符串输出功能调用(9号)。9号系统功能调用是将指定的内存缓冲区中字符串输出到屏幕上显示或到打印机上打印。9号功能调用要求缓冲区首地址必须由DS:DX给出,同时字符串必须以字符$结束。
例如,显示字符串“Hello!”,程序段编制如下:
BUF DB'Hello!', '$'
MOV DX, OFFSET BUF ; 入口参数
MOV AH, 09
INT 21H
执行上述的9号调用时,将在屏幕光标处输出整个字符串(不包括字符$)。
例如,利用DOS系统功能的9号和10号调用,可以实现人机对话。下面是一个简单的人机对话程序。
DATA SEGMENT
PARS DB 20 ; 定义缓冲区字节
DB ?
DB 20 DUP(?) ; 10号调用的输入字符串存储缓冲区
MESG DB'What is your name?' ; 要显示的提问信息
DB '$'
DATA ENDS
STACK SEGMENT PARA STACK 'STACK'
DB 100 DUP(?)
TOP LABEL WORD
STACK ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACK
START PROC FAR
BEGIN:PUSH DS
MOV AX,0
PUSH AX
MOV AX,DATA
MOV DS,AX
MOV AX,STACK
MOV SS,AX
MOV SP,TOP
DIAP: MOV DX,OFFSET MESG
MOV AH, 09 ; 9号调用显示提问信息
INT 21H
KEYBOD:MOV DX,OFFSET PARS
MOV AH,10
INT 21H ; 10号调用,等待从键盘上输入应答信息
RET ; 返回DOS操作系统
SART ENDP
CODES ENDS
EMD BEGIN
(5)从异步通信口输入单个字符调用(3号)。3号系统功能调用从异步通信口串行输入一个字符并送入AL中,无入口参数。
(6)向异步通信口输出单个字符(4号)调用。4号系统功能调用将DI中的字符向异步串行通信口输出,例如:
MOV DI,'A'
MOV AH,04H
INT 21H
(7)返回DOS(4CH 号)调用。4CH号功能调用使用的格式如下:
MOV AH,4CH
INT 21H
执行4CH号功能调用的结果是结束当前正在执行的程序,返回DOS系统,无入口参数。
(8)日期设置调用(2BH号)。2BH号功能调用是用来设置系统有效日期的。调用时寄存器CX中必须有一个有效年份(1980~2099),DH存放月份(01~12),DL中存放日期(1~31)。例如需要设置的日期为2004年9月18日,则设置日期程序段如下:
MOV CX,2004H
MOV DX,0918H
MOV AH,2BH
INT 21H
执行结果是将系统有效日期设置为2004年9月18 日,如果设置成功,则AL为0,否则AL为FFH(即-1)。
(9)读取日期调用(2AH号)。2AH号系统功能调用用于将系统当前日期读取到CX和DX寄存器中,是2BH号调用的逆过程,无入口参数,其使用格式如下:
MOV AH,2AH
INT 21H
执行结果是将年号送入CX寄存器中,月份和日期送入DX寄存器中。
(10)时间设置调用(2DH号)。2DH号系统功能调用设置系统时间,调用时要将入口参数有效时间送入CX和DX寄存器,其中CH存放时(0~23),CL存放分(0~59),DH存放秒(0~59),DL存放百分秒(0~99)。如要使当前系统时间为16点28分39.58秒,则其使用格式如下:
MOV CX,1628H ;CX←16:28
MOV DX,3958H ;DX←39"58
MOV AH,2DH
INT 21H
执行结果是将当前有效时间设置成16点28分39.58秒。如果设置成功,则将AL寄存器清零,否则把FFH(-1)送入AL寄存器。
(11)读取时间调用(2CH号)。2CH系统功能调用是将当前的系统时间读入CX和DX寄存器中,是2DH调用的逆过程,无入口参数,使用格式如下:
MOV AH,2CH
INT 21H
执行结果是将当前时间读入CX和DX寄存器中,存放格式与设置时间格式相同。