王爽 《汇编语言》 第15章 外中断 实验15:安装新的int 9中断例程

我写的程序如下(程序没问题):

;介绍:安装一个新的int 9中段例程,功能:在DOS下,按下“A”键后,除非不再松开,
;如果松开,就显示满屏幕的“A”;其他的键照常处理
assume cs:daima

daima segment
kaishi:
;------------------------------安装中断例程----------
mov ax,cs
mov ds,ax
mov si,offset int9

mov ax,0
mov es,ax
mov di,204h

mov cx,offset int9end-offset int9
cld
rep movsb
;---------------------------------------------------

;----------------------------保存原int 9的中断向量表------
mov ax,es:[4*9]
mov es:[200h],ax
mov ax,es:[4*9+2] ;保存在0:200h ——204h处
mov es:[202h],ax
;--------------------------------------------------

;-------------------设置新的int 9中断向量表----------
cli
mov word ptr es:[4*9],204h
mov word ptr es:[4*9+2],0
sti
;---------------------------------------------------

mov ax,4c00h
int 21h

int9:
push ax
push bx
push cx
push es

in al,60h ;得到键盘端口的输入

pushf
call dword ptr cs:[200h] ;调用原来的int 9例程 (这步有什么用,可以省略吗?)

cmp al,9eh ;是否为A的断码
jne int9ret

mov bx,0b800h
mov es,bx
mov di,0
mov cx,25*80
s:
mov byte ptr es:[di],'A' ;显示满屏幕的'A'
add di,2
loop s

int9ret:
pop es
pop cx
pop bx ;返回
pop ax
iret
int9end:nop

daima ends
end kaishi

这个程序运行正常,我的问题是:既然安装新的int9中断例程,又何必在运行新的中断例程的过程中又调用原来的int 9的中断例程,我试过了,少了这步确实不行,但这是为什么呢?不用这步操作程序看起来也没什么不完整的呀。请高手指点迷津。
in al,60h不是已经得到键盘的扫描码吗?这不是输入了吗?还要原来的int 9才能算输入? 我还没学接口技术?有高手能形象的解释一下好吗?

;本程序中用入栈、出栈的方式完成了 数据 在不同的寄存器之间的交换
;可以减少代码量,是个很不错的方法
assume cs:code

stack segment
db 128 dup (0) ;定义128个字节空间
stack ends

code segment
start:
mov ax,stack ;ss指向自定义栈空间
mov ss,ax
mov sp,128

push cs ;使ds,指向cs,为了完成子程序的copy
pop ds

mov ax,0 ;es指向子程序要去的段
mov es,ax

mov si,offset int9 ;指向要复制的偏移地址
mov di,204H ;指向要去的偏移地址
mov cx,offset int9end - offset int9 ;要复制的长度
cld ;正向复制
rep movsb ;循环复制

push es:[4*9] ;将原int 9的段地址入栈
pop es:[200H] ;将原int 9的段地址保存在0:200H处
push es:[4*9+2] ;将原偏移地址入栈
pop es:[202H] ;将原偏移地址保存在0:202H处

cli ;IF=0 , 防止执行可屏蔽中断
mov word ptr es:[4*9],204H ;重新设置int 9 的 段地址
mov word ptr es:[4*9+2],0H ;重新设置int 9 的偏移地址
sti ; IF=1

mov ax,4c00H ;结束程序
int 21H

;自定义int 9子程序
int9:
;保存可能用到的寄存器的值
push ax
push bx
push cx
push es

;从60H端口读入数据
in al,60H
;模拟int 指令调用功能
pushf ;保存标志寄存器的值
call dword ptr cs:[200H] ;调用原int 9 中断处理程序

cmp al,9eH ;判断是否为 A 的断码
jne int9ret ;若不是结束本次程序的执行

mov ax,0B800H ;es指向显存
mov es,ax
mov bx,0 ;bx指向每次显示'A'的偏移地址
mov cx,2000 ;显示'A'个数
s: ;循环显示'A'
mov byte ptr es:[bx],'A'
add bx,2
loop s

int9ret:
;还原寄存器的值
pop es
pop cx
pop bx
pop es
iret
int9end:
nop

code ends
end start

;这个程序要在纯Dos下运行
温馨提示:答案为网友推荐,仅供参考
第1个回答  2010-09-25
改下
in al,60h
是I\O输入和输出
并不是得到一个A的字符码
相当于连接键盘端口
然后调用原int 9
相当于
out al,60h
从端口输出一个字符的断码
就是
int 9中断的作用是得到一个键盘输入的字符的断码
而新的int 9中断的作用是仅仅是比较你输入字符断码是不是A,是则打印一屏幕的A
如果没有以前的int 9中断
那么字符又如何输入进入
那么新的int 9中断就废了

汇编不是很好
大家可以都相互学习学习