汇编学习笔记(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处已有程序占用

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

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

会不会是这个原因造成的呢?试试就知道了,继续使用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!

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

你可能感兴趣的:(学习笔记)