[Hb-XII] 编写0号中断的处理程序

《汇编语言·第三版》--王爽


1 8086内中断过程

[Hb-XII] 编写0号中断的处理程序_第1张图片
Figure1. 8086内中断过程

中断信息的中断类型码标识中断信息的来源。


多个中断向量连续存储在一片内存中构成中断向量表。


中断向量即为中断处理程序的入口地址。


8086PC机中断类型码N的中断向量的地址为(4 * N + 2):(4 * N),中断类型码从0开始编号,从内存0000:0到0000:03FF的1024个单元存放中断向量表。如内中断“除法错误”、“单步执行”、“执行into指令”的中断类型码分别为0、1、2。

2 题目

编写0号中断的处理程序,使得在除法溢出发生时,在屏幕中间显示字符串“divide error!”,然后返回到DOS。要求,仔细跟踪调试,在理解整个过程之前,不要进行后面课程的学习。


3 代码

1.        assume              cs:codesg

2.         

3.        codesg               segment

4.        start:

5.                  mov           ax, cs

6.                  mov           ds, ax

7.                  mov           si,offset do0              ;用ds:[si]指向需要被复制的程序

8.                 

9.                  mov           ax, 0

10.              mov           es, ax

11.              mov           di, 200h                       ;用es:[di]指向程序被复制的目的地址

12.             

13.              mov           cx,offset do0end - offset do0

14.              cld

15.              rep             movsb                          ;使用串传送指令,从ds:[si]传送cx字节到es:[di]

16.             

17.              mov           ax, 0

18.              mov           es, ax

19.              mov           word ptr es:[0 * 4], 200h

20.              mov           word ptr es:[0 * 4 + 2], 0  ;设置中断向量表,N号中断的中断程序入口地址保存在(N * 4 + 2):(N * 4)内存中

21.               ;中断程序可以在任意内存中,由于8086PC机中0000:0 ~ 0000:03FF是专门存放中断程序入口地址的内存区

22.               ;且0000:0200 ~0000:02FF内存区空间所对应的中断向量表是空的(没有那么多的中断),操作系统也不占用这段空间

23.               ;故而将中断程序拷贝到这段空间内

24.              mov           ax,1000h

25.              mov           bh, 1

26.              div              bh                                                    ;会造成除法溢出的汇编代码                                                        

27.             

28.              mov           ax,4c00h

29.              int              21h

30.             

31.    do0: jmp short do0start

32.              db "divide error!"

33.     

34.    ;-------被拷贝到0000:0 ~0000:02FF内存段的中断服务程序-------

35.    do0start:          

36.                                 push          ax

37.                                 push          cx

38.                                 push          ds

39.                                 push          es

40.                                 push          si

41.                                 push          di

42.                                

43.                                 mov           ax,cs        ;由do0中跳转过来,此时CS指向do0start这个段,这个段被拷贝到0000:0200~ 0000:02FF段中

44.                                 mov           ds,ax

45.                                 mov           si,202h    ;“jmp      short do0start”指令占两个字节

46.     

47.                                 mov           ax,0b800h

48.                                 mov           es,ax

49.                                 mov           di,12 * 160 + 36 * 2 ;屏幕中间所对应显存起始地址

50.                                

51.                                 mov           cx,12

52.                                 s:

53.                                                    mov           al, [si]

54.                                                    mov           es:[di], al

55.                                                    mov           byte ptr es:[di + 1], 4                  ;红色

56.                                                    inc              si

57.                                                    add            di, 2

58.                                                    loop           s

59.                                

60.                                 pop            ax

61.                                 pop            di

62.                                 pop            si

63.                                 pop            es

64.                                 pop            ds

65.                                 pop            cx

66.                                 iret

67.    ;-------被拷贝到0000:0 ~0000:02FF内存段的中断服务程序-------

68.    do0end:nop

69.    codesg               ends

70.    end            start

中断例程中要显示的字符串与中断例程保存在一起,保存到他处有可能被释放(栈空间)。(注:do0start程序中,各寄存器的入栈备份和出栈恢复值的顺序是不正确的。

4 测试结果

将以上一段程序命名为l12.asm,编译连接12.asm后直接运行得到如下结果:
[Hb-XII] 编写0号中断的处理程序_第2张图片
Figure2. 编号为0的中断服务程序(截屏未截完)

5 跟踪调试

[Hb-XII] 编写0号中断的处理程序_第3张图片
Figure3. 0号中断服务程序拷贝至0000:0200 ~ 0000: 024f处完成
[Hb-XII] 编写0号中断的处理程序_第4张图片
Figure4. 往0号中断的中断向量内存中写入中断向量(中断服务程序的入口地址)

Figure5. 除法中断发生前,未有任何栈操作
[Hb-XII] 编写0号中断的处理程序_第5张图片
Figure6. 当发生除法溢出时,进入0中断服务程序内,栈也开始使用

Figure7. 进入中断程序时,flag CS IP入栈
[Hb-XII] 编写0号中断的处理程序_第6张图片
Figure8. IP的压栈值时DIV BH这条指令
[Hb-XII] 编写0号中断的处理程序_第7张图片
Figure9. 中断程序返回后再执行原来发生除法溢出的那条指令处
[2014.12.19 - 17:16]
R《Hb》Note Over.

你可能感兴趣的:([Hb-XII] 编写0号中断的处理程序)