汇编学习笔记(10)内中断

中断,可以理解为"从中间断开",再加上主语就是"从程序流中断开",即CPU不再接着预先定义的代码向下执行,转而去处理中断的信息,有内中断和外中断之分。

内中断

内中断是由计算机内部产生的中断信息,8086CPU有以下4种内中断信息:

  • 除法错误,中断码0
  • 单步执行,中断码1
  • into指令,中断码4
  • int指令,中断码int n

中断向量表

中断向量表就是存放中断处理程序入口地址的列表。程序的地址由CS:IP表示,所以一个入口地址占4个字节,高位存放段地址,低位存放偏移地址。中断码由一个字节表示最大为256个,故中断向量表为1024字节,8086中的内存地址为0000:0000~0000:03FF.

中断过程

8086CPU执行中断操作过程如下:

1.取得中断码
  2.标志寄存器的值入栈,设置TF,IF=0
  3.CS,IP入栈
  4.中断程序的入口地址,cs=(中断码*4),ip=(中断码*4+2)

用伪代码描述如下:

1.取得中断码N
  2.pushf,TF=0,IF=0
  3.push cs,push ip
  4.(cs)=(N*4),(ip)=(N*4+2)

编写中断处理程序

编写中断程序和子程序相似,不同的地方是用iret代替ret指令返回,iret指令完成的功能是pop ip,pop cs,popf.为什么要加上pop f呢?因为在中断过程中取得中断码后将标志寄存器入栈pushf所以在执行完成中断程序后需要将标志寄存器的值出栈。

下面从头开始编写除法错误时的中断程序,我们想要达到的效果是发生除法错误时在屏幕中间输出"overflow",中断程序放在0000:0020~0000:02FF这段内存空间中。

根据中断的执行过程来看,我们首先要考虑的是如何把中断程序的地址设置在中断向量表中,为此我们编写如下代码

1     mov ax,0000h
2     mov es,ax
3     mov si,0
4     mov word ptr es:[si],200h
5     mov word ptr es:[si+2],0

 

设置好中断向量表后,接下来要进行的是将中断程序div0复制到0000:0020开始的内存单元中

 1 assume cs:code
 2 
 3 code segment
 4 
 5 start:
 6     ;将0020:0000写入中断向量表0号中断码的地址
 7     mov ax,0000h
 8     mov es,ax
 9     mov si,0
10     mov word ptr es:[si],200h
11     mov word ptr es:[si+2],0
12     
13     ;设置ds:si指向div0
14     mov ax,cs
15     mov ds,ax
16     mov si,offset div0
17     ;设置es:di指向0000:0020
18     mov ax,0
19     mov es,ax
20     mov di,0020h
21     
22     ;将div0长度传入cx
23     mov cx,offset div0end-offset div0
24     
25     cld ;设置df=0,si,di递增
26     ;传输div0
27     rep movsb
28     
29     mov ax,4C00h
30     int 21h
31 
32 div0:
33     ...
34 div0end:
35     nop     
36     
37 code ends
38 end start

 

前期的准备工作做好后,就可以开始编写中断程序div0了

 1 assume cs:code
 2 
 3 code segment
 4 
 5 start:
 6     
 7     ;设置ds:si指向div0
 8     mov ax,cs
 9     mov ds,ax
10     mov si,offset div0
11     ;设置es:di指向0000:0020
12     mov ax,0
13     mov es,ax
14     mov di,0020h
15     
16     ;将div0长度传入cx
17     mov cx,offset div0end-offset div0
18     
19     cld ;设置df=0,si,di递增
20     ;传输div0
21     rep movsb
22     
23     ;将0020:0000写入中断向量表0号中断码的地址
24     mov ax,0000h
25     mov es,ax
26     mov si,0
27     mov word ptr es:[si],200h
28     mov word ptr es:[si+2],0
29     
30     mov ax,4C00h
31     int 21h
32 
33 div0:
34     ;'overflow'若放在主程序中,当主程序执行完成后内存单元释放,'overflow'所在
35     ;内存单元有可能会被其他程序占用
36     jmp short div0start
37     db 'overflow'
38 
39 div0start:
40     ;ds:si指向'overflow'
41     mov ax,cs
42     mov ds,ax
43     ;jmp short div0start占两个字节
44     mov si,202h
45     
46     ;屏幕中间显示
47     mov ax,0b800h
48     mov es,ax
49     mov di,160*12+36*2
50     
51     mov cx,9
52 
53 s:
54     mov al,ds:[si]
55     mov es:[di],al
56     inc si
57     add di,2
58     loop s
59     
60     mov ax,4C00h
61     int 21h
62     
63 div0end:
64     nop     
65     
66 code ends
67 end start

 

写完编译运行,发现程序卡住不动了,这是什么情况?Debug查看后发现,0000:0020处已有程序占用

会不会是这个原因造成的呢?试试就知道了,继续使用d命令查找空闲内存,发现01e0开始的内存空间都是空闲的,故修改代码如下

 1 assume cs:code
 2 
 3 code segment
 4 
 5 start:
 6     
 7     ;设置ds:si指向div0
 8     mov ax,cs
 9     mov ds,ax
10     mov si,offset div0
11     ;设置es:di指向0000:01e0
12     mov ax,0
13     mov es,ax
14     mov di,01e0h
15     
16     ;将div0长度传入cx
17     mov cx,offset div0end-offset div0
18     
19     cld ;设置df=0,si,di递增
20     ;传输div0
21     rep movsb
22     ;mov al,ds:[si]
23     ;mov es:[di],al
24     ;inc di
25     ;inc si
26 ;s1:
27     ;movsb
28     ;loop s1
29     
30     ;将01e0:0000写入中断向量表0号中断码的地址
31     mov ax,0000h
32     mov es,ax
33     mov si,0
34     mov word ptr es:[si],01e0h
35     mov word ptr es:[si+2],0
36     
37     int 0
38     
39     mov ax,4C00h
40     int 21h
41 
42 div0:
43     ;'overflow'若放在主程序中,当主程序执行完成后内存单元释放,'overflow'所在
44     ;内存单元有可能会被其他程序占用
45     jmp short div0start
46     db 'overflow'
47 
48 div0start:
49     ;ds:si指向'overflow'
50     mov ax,cs
51     mov ds,ax
52     ;jmp short div0start占两个字节
53     mov si,01e2h
54     
55     ;屏幕中间显示
56     mov ax,0b800h
57     mov es,ax
58     mov di,160*12+36*2
59     
60     mov cx,8
61 
62 s:
63     mov al,ds:[si]
64     mov es:[di],al
65     inc si
66     add di,2
67     loop s
68     
69     mov ax,4C00h
70     int 21h
71     
72 div0end:
73     nop     
74     
75 code ends
76 end start

 

编译运行,没问题,OK!

posted @ 2014-01-22 20:39  huntstack  阅读(505)  评论(0编辑  收藏  举报