外中断(学习汇编)
外中断是指那些不再CPU内部产生的中断,即通过端口与cpu通信的外设产生的中断。
- 可屏蔽中断是CPU可以不响应的外中断
- 不可屏蔽中断是CPU必须响应的中断,其中断类型码都是2
- sti,cli可以屏蔽中断,让一些如改变中断向量的操作安全进行。
1. 可屏蔽中断,CPU根据标志寄存器IF位决定是否响应中断,IF=1,响应中断,IF=0,不响应中断。
sti,用于设置IF=1;
cli,用于设置IF=0。
2. 不可屏蔽中断,CPU必须响应中断。不可屏蔽中断的中断类型码固定为2,所以中断过程中,不需要取中断类型码。则不可屏蔽中断的中断过程为:
(1)标志寄存器入栈,IF=0,TF=0;
(2)CS、IP入栈;
(3)(IP)=(8),(CS)=(0AH)。
程序1:在屏幕中某个位置一次输出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
mov ax,0
mov es,ax
push es:[9*4]
pop ds:[0]
push es:[9*4+2]
pop ds:[2]
mov word ptr es:[9*4],offset int9
mov es:[9*4+2],cs
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
push ds:[0]
pop es:[9*4]
push ds:[2]
pop es:[9*4+2]
mov ax,4c00h
int 21h
delay:
push ax
push dx
mov dx,10h
mov ax,0
s1:
sub ax,1 ;sbb带借位减法指令0-1=ffff,CF=1
sbb dx,0 ;(dx)=(dx)-0-CF
cmp ax,0 ;相当于ffff*1000次
jne s1
cmp dx,0
jne s1
pop dx
pop ax
ret
int9: push ax
push bx
push es
in al,60h
pushf
pushf
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
code ends
end start
程序2:按f1改变屏幕显示颜色。
;cs总在高地址处
assume cs : codesg, ss : stacksg
stacksg segment
dw 64 dup (0)
stacksg ends
codesg segment
start: mov ax, stacksg
mov ss, ax
mov sp, 128
mov ax, 0
mov es, ax
mov ax, codesg
mov ds, ax
mov si, offset int9s
mov di, 0200h
cli
mov bx, offset table
mov ax, es : [9 * 4]
mov [bx], ax
mov ax, es : [9 * 4 + 2]
mov [bx + 2], ax
mov word ptr es : [9 * 4], 0200h
mov word ptr es : [9 * 4 + 2], 0
sti
mov cx, offset int9end - offset int9s
cld
rep movsb
mov ax, 4c00h
int 21h
int9s: jmp short sss
table dw 0, 0
sss: push ds
push ax
push cx
push si
pushf
mov ax, 0
mov ds, ax
call dword ptr ds : [202h]
in al, 60h
cmp al, 3bh
jne int9ret
mov si, 0
mov cx, 2000
mov ax, 0b800h
mov ds, ax
s1: inc byte ptr [si + 1]
add si, 2
loop s1
int9ret: pop si
pop cx
pop ax
pop ds
iret
int9end: nop
codesg ends
end start
程序3:在DOS下,按下'A'键后,松开就显示满屏幕‘A’。
;中断时的入栈顺序是pushf,push cs, push ip
assume cs : codesg, ss : stacksg
stacksg segment
dw 64 dup (0)
stacksg ends
codesg segment
start: mov ax, stacksg
mov ss, ax
mov sp, 128
mov ax, 0
mov es, ax
mov di, 0200h
mov si, offset int9
push cs
pop ds
cli
mov bx, offset table
mov ax, es : [9 * 4]
mov ds : [bx], ax
mov ax, es : [9 * 4 + 2]
mov ds : [bx + 2], ax
sti
mov cx, offset int9end - offset int9
cld
rep movsb
mov word ptr es : [9 * 4 + 2], 0
mov word ptr es : [9 * 4], 0200h
mov ax, 4c00h
int 21h
int9: jmp short s
table dw 0, 0
s: push ax
push cx
push si
push es
mov ax, 0
mov ds, ax
pushf
call dword ptr ds : [202h]
in al, 60h
cmp al, 9eh
jne int9ret
mov ax, 0b800h
mov es, ax
mov si, 0
mov cx, 2000
s1: mov byte ptr es : [si], 'A'
add si, 2
loop s1
int9ret:pop es
pop si
pop cx
pop ax
iret
int9end:nop
codesg ends
end start