汇编语言(王爽第三版)检测点15

检测点 15.1

(1)仔细分析一下上面的int 9中断例程,看看是否可以精简一下?

       其实在我们的int 9中断例程中,模拟int指令调用原int 9中断例程的程序段是可以精简的,因为在进入中断例程后,IF和TF都已经置零,没有必要再进行设置了。对于程序段:

              pushf                           ;将寄存器值入栈

              pushf                           ;将寄存器值入栈

              pop ax                          ;弹栈到ax中,(ax)=(flag)

              and ah, 11111100b  ;注意是高8位,IF和TF是标志位中的第9和第8位,按位与

              push ax                        ;将修改后的值入栈。

              popf                            ;将修改后的值弹栈到标准寄存器中。这时IF=0,TF=0

              call word ptr ds:[0];调用原来的int9中断例程。

可以精简为:

 pushf                  

 call word ptr ds:[0] 

两条指令。

       程序分析:

【1】由于我们无论是调用那个中断处理例程,CPU都干如下的活:

       (1)从中断信息中取得中断类型码

       (2)标志寄存器入栈保存(因为在中断过程中要改变标志寄存器的值。)

       (3)设置标志寄存器的第8位TF(跟踪标志)和第9位IF(中断标志)为0.(防止单步中断和其他外部中断发生)

       (4)cs的内容入栈

       (5)IP的内容入栈

       (6)设置ip的值为:N(中断类型码)*4;设置cs的值:N*4+2

       所以第二个pushf是多余的指令,然后是设置IF和TF的指令也是多余的了。

【2】为什么还有个pushf呢,这个pushf指令压栈标志寄存器,确实是保护标志寄存器的值,也是为了与中断程序中的iret(它内部CPU操作步骤有popf)相呼应。如果没有这个pushf,那么iret指令执行中出栈到标准寄存器的值可能不正确了。

(2)仔细分析上面程序中的主程序,看看有什么潜在的问题?

       在主程序中,如果在执行设置int 9中断例程的段地址和偏移地址的指令之间,发生了键盘中断,则CPU将转去一个错误的地址执行,将发生错误。

       找出这样的程序段,改写它们,排除潜在的问题。

       提示:注意sti和cli指令的用法。

程序分析:

【1】关于设置中断向量表的指令,在程序中就2段。

mov word ptr es:[9*4], offset int9

mov es:[9*4+2], cs          ;将新的int9入口地址写入中断向量表中

---

; 将中断向量回写回中断向量表中

        mov ax, 0

        mov es, ax                  ;将es指向0000段内存中断向量表

        push ds:[0]

        pop es:[9*4]

        push ds:[2]

        pop es:[9*4+2] 

       如果在指令执行在这2段中间,引发了键盘中断事件,由于正在设置中断向量表,故(ip)和(cs)值可能不确定。为了避免这2段代码不受到中断事件的干扰,将中断屏蔽了。

【2】sti和cli指令的用法:

       cli 禁止中断发生
       sti 允许中断发生

【3】这二段代码前后加上cli和sti指令即可:

;在中断向量表中设置新的中断入口地址的时候不让其发生中断

cli

mov word ptr es:[9*4],offset int9

mov word ptr es:[9*4+2],cs

sti

 

恢复中断向量表int9的源地址时:

cli

push ds:[0]

pop es:[9*4]

push ds:[2]

pop es:[9*4+2]

sti

 

posted @ 2017-05-21 09:39  筑基2017  阅读(1447)  评论(1编辑  收藏  举报