int 9中断例程;在屏幕中间依次显示'a'~'z',并可以让人看清。 在显示的过程中,按下Esc键后,改变显示的颜色

;在屏幕中间依次显示'a'~'z',并可以让人看清。
;在显示的过程中,按下Esc键后,改变显示的颜色

assume cs:code

stack segment
db 128 dup(0)
stack ends

data segment
dw 0, 0
data ends

code segment
start:
;设置栈
mov ax, stack
mov ss, ax
mov sp, 128

;设置数据段
mov ax, data
mov ds, ax


;--将原来的int 9中断例程的入口地址保存在ds:0[IP]、ds:2[CS]单元中
mov ax, 0
mov es, ax
push es:[9*4]
pop ds:[0] ;IP
push es:[9*4+2]
pop ds:[2] ;CS

;--在中断向量表中设置新的int 9中断例程的入口地址
mov word ptr es:[9*4], offset int9
mov es:[9*4+2], cs

;--在屏幕中央显示字符
mov ax, 0b800h
mov es, ax
mov ah, 'a' ;ah保存'a'的ASCII
s:
mov byte ptr es:[160*12+40*2], ah
call delay
inc ah ;ah = ah + 1
cmp ah, 'z' ;
jna s ;if(ah!='z'){jmp short s}
;jna 不高于则转义 cf=1或zf=1

;--将中断向量表中int 9中断例程的入口恢复为原来的地址
mov ax, 0
mov es, ax
push ds:[0]
pop es:[9*4] ;IP
push ds:[2]
pop es:[9*4+2] ;CS

;--程序返回
mov ax, 4c00h
int 21h


;--缓冲显示字符
delay:
push ax
push dx

mov dx, 1h ;循环1000 0000次
mov ax, 0 ;(dx)=(高16位) (ax)=(低16位)
s1:
sub ax, 1 ;(低16位[0000])-(1) 借位CF=1
sbb dx, 0 ;(高16位[0001])-0-CF
cmp ax, 0
jne s1 ;jne 不等于则转义
cmp dx, 0
jne s1 ;jne 不等于则转义

pop dx
pop ax
ret

;--新的int 9中断例程
int9:
push ax
push bx
push es

in al, 60h

;--int指令执行过程
; 1、取中断类型码
; 2、标志寄存器入栈、(IF)=0, (TF)=0
; 3、CS、IP入栈
; 4、(IP)=(n*4)、(CS)=(n*4+2)
;--iret指令执行过程
; 1、CS、IP出栈
; 2、标志寄存器出栈

;//模拟int
;a、pushf将标志寄存器的值压栈
pushf
;b、将标志寄存器 (IF)=0, (TF)=0
pushf ;第二次入栈是为了设置flag标志寄存器中
pop bx
and bh, 11111100b ;将标志寄存器 (IF)=0, (TF)=0
push bx
popf ;popf从栈中弹出数据送入标志寄存器中
;c、执行中断例程
call dword ptr ds:[0] ;对int指令进行模拟,调用原来的int 9中断例程
;(IP)=ds:[0] (CS)=ds:[2]
cmp al, 1
jne int9ret

mov ax, 0b800h
mov es, ax
inc byte ptr es:[160*12+40*2+1] ;属性增加1,改变颜色

int9ret:
pop es
pop bx
pop ax
iret
code ends
end start

 

 

原文地址:https://www.cnblogs.com/qintangtao/p/2868233.html