汇编语言(王爽第三版)实验15 安装新的int 9中断例程
实验15 安装新的int 9中断例程
安装一个新的int 9中断例程,功能:在DOS下,按下“A”键后,除非不再松开,如果松开,就显示满屏幕的“A”,其他的键照常处理。
提示:按下一个键时产生的扫描码称为通码,松开一个键产生的扫描码称为断码。断码=通码+80h
程序分析:
【1】这个程序是个中断例程的安装程序,还是老样子,在0:200处安装复制新的中断例程机器码,并设置中断向量表的入口地址为0:200。
如何测试?执行这个安装程序,在DOS下,按下A,松开后显示满屏的A。测试不了的。不是DOS的实模式。
【2】将原来的int 9中断例程的入口地址保存在ds:200、ds:202单元中,这个地方比较安全。
【3】先编写一个中断程序:(就叫int9)
A的通码是:1EH,断码是:1EH+80H=9EH
汇编代码如下:
;------
;程序名称:int9(新的)
;功能:中断例程,当按下A键,松开时,屏幕显示满屏的A。
;入口参数:无
;返回值:无
;-------
int9: ;保护寄存器变量
push ax
push bx
push es
push cx
;从端口60h中读出扫描码
in al, 60h
;模拟BIOS中的原来的中断例程int 9
pushf ;将寄存器值入栈
call word ptr ds:[200H];调用原来的int9中断例程。
cmp al, 9EH ;A键通码是1EH,断码是9EH,与端口读出的扫描码比较
jne int9ret
;满屏显示A字符
mov ax, 0b800H
mov es, ax ;es指向显存缓冲区
mov bx, 0
mov cx, 2000 ;80列*25行共2000个字符。
Awrite: mov byte ptr es:[bx], 41H ;A的ASCII码是41H
add bx, 2 ;一个字符占2个字节,故偏移增量为2
loop Awrite
int9ret:pop cx
pop es
pop bx
pop ax
iret
【4】最后写个安装程序,将新编写的int 9中断例程写入到0:200处开始的内存,其中[200H]和[202H]存放原来的例程的入口地址。
assume cs:code
code segment
start: ;int 9中断例程的安装程序
;mov ax, cs
;mov ds, ax
;可以使用栈,这样赋值
push cs
pop ds
mov si, offset int9 ;将ds:si指向源地址(int9的机器码)
mov ax, 0000H
mov es, ax
mov di, 204H ;将es:di指向目的地址(0:204H向量表中)
;前2个字用来存储原来的例程的入口地址
mov cx, offset int9end - offset int9 ;设置传输长度
cld ;传输方向为正
rep movsb ;字节传输
mov ax, 0000H
mov es, ax
;将原来的例程的入口地址保存在0:200H处,共2个字单元。
push es:[9*4] ;将向量表中9号ip压栈
pop es:[200H] ;弹栈到0:200H处
push es:[9*4+2] ;将向量表中9号cs压栈
pop es:[202H] ;弹栈到0:202H处
;设置中断向量表,使9条目中断向量指向0000:204H
cli
mov word ptr es:[9*4], 204H
mov word ptr es:[9*4+2], 0000H
sti
mov ax, 4c00H
int 21H
;------装载的例程
;程序名称:int9(新的)
;功能:中断例程,当按下A键,松开时,屏幕显示满屏的A。
;入口参数:无
;返回值:无
;-------
int9: ;保护寄存器变量
push ax
push bx
push es
push cx
;从端口60h中读出扫描码
in al, 60h
;模拟BIOS中的原来的中断例程int 9
pushf ;将寄存器值入栈
call word ptr ds:[200H];调用原来的int9中断例程。
cmp al, 9EH ;A键通码是1EH,断码是9EH,与端口读出的扫描码比较
jne int9ret
;满屏显示A字符
mov ax, 0b800H
mov es, ax ;es指向显存缓冲区
mov bx, 0
mov cx, 2000 ;80列*25行共2000个字符。
Awrite: mov byte ptr es:[bx], 41H ;A的ASCII码是41H
add bx, 2 ;一个字符占2个字节,故偏移增量为2
loop Awrite
int9ret:pop cx
pop es
pop bx
pop ax
iret
int9end: nop ;代码段结尾,便于计算7cH例程的长度。
code ends
end start
程序分析:
【1】不像前面章节中的中断例程,安装完毕后可以测试下。这个程序依然不能测试。自己体会吧。只有安装了DOS系统下才能测试。
【2】临时存储原来int9中断例程的中断向量的空间在代码段中的[200H]~[203H]中,我们一般不在代码段中存储数据。代码段只是存储CPU执行的代码。
【3】此程序可谓是一体的,测试程序和安装程序都在一个程序段内,没有了原来上面章节中介绍的例程装载程序。将中断例程直接写到了code段中。
【4】在命令提示符窗口中,可以运行此程序,但不能使用int 9中断程序。也就是说在程序中从a到z变化过程中,我们不能按任何键(会调用中断int9的,而且是新的中断例程),由于中此程序中断向量表不能正常更新,故int9程序调用时出错!
【5】理解这个程序吧,除非我们处在DOS环境中。其实玩汇编就是在DOS下的,写写操作系统啦,编个程序啦。