|
5鱼币
int指令在执行的时候,cpu进行下面的工作():
1.取中断类型码n
2.标志寄存器入栈
3.if=0,tf=0
4.cs,ip入栈
5.(ip)=(n*4),(cs)=(n*4+2)
程序功能:在屏幕中间依次显示“a”~“z”,并可以让人看清。在显示的过程中,按下'Esc'键后,改变显示的颜色。
思考了很久都搞不懂,第十五章,模拟int 9那里的情况,当我按下esc产生外中断,正常情况是上边的1到5步骤.而我们模拟的时候:按下esc,然后cpu检查到端口的扫描码产生外中断9号信息提供申请,cpu检测到中断信息9就开始把标志寄存器入栈,if,tf设置为0,我只是改变了中断向量表的指向的中断例程,第4,5步是在call之后进行的我知道,第1步也是事先知道了.
那么我的问题来了,那么第2,第3步,假如是已经int之后就达到目的了(没有调用中断例程之前),也就是完成了第2,第3步,为什么在模拟的中断例程中需要再来一遍第2,第3步
假如是在根据中断向量表指向的cs,ip跳转后才实现的第2,第3步,那么在新写的int 9里边包含了指向原来的中断例程,也就是下边源码的call dword ptr ds:[0],那不就等于执行了两次重复的动作,模拟第2第3步就显得多余了
因为代码只是改动了中断向量表指向的中断例程,我的理解就是它属于例程后的例程(属于例程的补充),所以我就被它的模拟搞糊涂了,希望大佬讲解,以下为源码:
分割线---------------------------------------------------------------------------------------------------------------------------------------------------
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] ;将原来的int 9中断例程的入口地址保存在ds:0、ds:2单元中
mov word ptr es:[9*4],offset int9
mov es:[9*4+2],cs ;在中断向量表中设置新的int 9中断例程的入口地址,使得中断的时候执行新的int 9
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] ;将中断向量表中int 9中断例程的入口恢复为原来的地址
mov ax,4c00h
int 21h
delay:
push ax
push dx
mov dx,2000h
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 9中断例程--------------------
int9:
push ax
push bx
push es
in al,60h;取60h端口中的扫描码
pushf
pushf;一次模拟的,一次还原真实的9号中断寄存器
pop bx
and bh,11111100b
push bx
popf;if和cf都设置好了,再执行下一步call后,当前cs,ip进栈,还有跳转到对应的cs,ip取执行中断例程
call dword ptr ds:[0] ;对int指令进行模拟,调用原来的int 9中断例程/////
cmp al,1;esc的扫描码为1
jne int9ret
mov ax,0b800h
mov es,ax
inc byte ptr es:[160*12+40*2+1] ;如果此时是esc键,属性增加1,改变颜色
int9ret:
pop es
pop bx
pop ax
iret
code ends
end start
|
|