汇编语言(王爽第三版)实验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下的,写写操作系统啦,编个程序啦。

 

posted @ 2017-05-21 09:40  筑基2017  阅读(879)  评论(0编辑  收藏  举报