首先完成书上的int9例程:实现按下esc键,改变显示的颜色后返回。
Int9 处理过程:
1. 读出60h端口扫描码。(In al,60h)
2. 调用BIOS的int9 中断例程,处理其他硬件细节。(理解为这一步需要两个调用一次旧中断,一次新中断。需要保存旧中断的段地址和偏移地址。)
3. 判断读取到的字符的扫描码。
assume cs:code,ss:stack,ds:data
data segment
dw 0,0
data ends
stack segment
db 128 dup(0)
stack ends
code segment
start:
mov ax,stack ;初始化栈
mov ss,ax
mov sp,128
mov ax,data
mov ds,ax
mov ax,0
mov es,ax
cli ;cli保证数据安全
push es:[9*4]
pop ds:[0]
push es:[9*4+2]
pop ds:[2] ;将原来的int9地址保存在ds:0 ds:2单元中
;设置中断向量表偏移地址、段地址
mov word ptr es:[9*4],offset int9
mov es:[9*4+2],cs
sti
call clear_screen
;显示字符串
mov ax,0b800h
mov es,ax
mov ah,'a'
s:
mov es:[160*12+40*2],ah
call delay
inc ah
cmp ah,'z'
jna s
;恢复原来的地址
mov ax,0
mov es,ax
cli
push ds:[0]
pop es:[9*4]
push ds:[2]
pop es:[9*4+2]
sti
mov ax,4c00h
int 21h
;延迟函数
delay:
push ax
push dx
mov dx,10h
mov ax,0
s1:
sub ax,1
sbb dx,0
cmp ax,0
jne s1
cmp dx,0
jne s1
pop dx
pop ax
ret
;int9新中断
int9:
push ax
push bx
push es
in al,60h ; 第一步,读取60端口中断码
pushf ;标志寄存器入栈
pushf ;修改if tf
pop bx
and bh,11111100b
push bx
popf
call dword ptr ds:[0] ;调用原来的中断
cmp al,1
jne int9ret
mov ax,0b800h
mov es,ax
inc byte ptr es:[160*12+40*2+1]
int9ret:
pop es
pop bx
pop ax
iret
clear_screen:
mov ax,0b800h
mov es,ax
mov cx,2000
mov dx,0700h
mov di,0
cleanrScreen:
mov es:[di],dx
add di,2
loop cleanrScreen
ret
code ends
end start
实验15 如下:
在上边的基础上做了一点修改。
assume cs:code,ss:stack,ds:data
data segment
dw 0,0
data ends
stack segment
db 128 dup(0)
stack ends
code segment
start:
mov ax,stack ;初始化栈
mov ss,ax
mov sp,128
mov ax,data
mov ds,ax
mov ax,0
mov es,ax
cli
push es:[9*4]
pop ds:[0]
push es:[9*4+2]
pop ds:[2] ;将原来的int9地址保存在ds:0 ds:2单元中
sti
;设置中断向量表偏移地址、段地址
mov word ptr es:[9*4],offset int9
mov es:[9*4+2],cs
call clear_screen
;显示字符串
mov ax,0b800h
mov es,ax
mov ah,'a'
s:
mov es:[160*12+40*2],ah
call delay
inc ah
cmp ah,'z'
jna s
;回复原来的地址
mov ax,0
mov es,ax
cli
push ds:[0]
pop es:[9*4]
push ds:[2]
pop es:[9*4+2]
sti
mov ax,4c00h
int 21h
;延迟函数
delay:
push ax
push dx
mov dx,10h
mov ax,0
s1:
sub ax,1
sbb dx,0
cmp ax,0
jne s1
cmp dx,0
jne s1
pop dx
pop ax
ret
;int新中断
int9:
push ax
push bx
push es
push cx
in al,60h ; 第一步,读取60端口中断码
pushf ;标志寄存器入栈
pushf ;修改if tf
pop bx
and bh,11111100b
push bx
popf
call dword ptr ds:[0] ;调用原来的中断
cmp al,9eh ;判断是否为a的断码
jne int9ret
mov ax,0b800h
mov es,ax
mov bx,0
mov cx,2000
sa:
mov byte ptr es:[bx],'A'
add bx,2
loop sa
int9ret:
pop cx
pop es
pop bx
pop ax
iret
clear_screen:
mov ax,0b800h
mov es,ax
mov cx,2000
mov dx,0700h
mov di,0
cleanrScreen:
mov es:[di],dx
add di,2
loop cleanrScreen
ret
code ends
end start
按下a送开后: