若余相思 发表于 2017-12-1 09:47:27

第十二章 内中断

本帖最后由 若余相思 于 2017-12-1 09:47 编辑

中断信息的含义:CPU在执行完当前正在执行的的指令之后,检测从CPU外部发来或内部产生的一种特殊的信息,
并且立即对所收到的信息进行处理

12.1节   中断的产生

当CPU有如下的情况发生时,将产生相应的中断信息

(1)除法错误
(2)单步执行
(3)执行into指令
(4)执行int指令

中断信息包含中断类型码,该码为一个字节数据类型,可以表述256种中断信息。比如除法错误的类型码是0


12.3节   中断向量表

中断必须要找到中断的地址来说设置CS和IP,然而去哪找呢?

中断向量表保存着256个中断源所对应的中断处理程序的入口地址

中断向量表存放在内存中,从0开始,从0000:0000到0000:03FF的1024个单元的中存放着中断向量表,不能存放在别处

中断处理程序的入口地址包括段地址和偏移地址,故一个表项中占两个字。高地址存放段地址,地址地存放偏移地址。

从而可以得知,存储N号中断源的中断处理程序入口的偏移地址为4N,段地址为4N + 2


12.4节   中断过程

中断在接收到中断的入口地址时,必须先保存原来的CS和IP以便恢复到原来的状态

中断的过程:
(1)取得中断类型码(从中断信息中获取)
(2)将标志寄存器的值入栈
(3)设置标志寄存器的第8位TF和第9位的IF的值位0
(4)CS入栈
(5)IP入栈
(6)将中断类型码N*4和N*4 + 2的两个字单元读取的中断处理程序入口地址设置为IP和CS

用更简洁的描述就是:
(1)取得中断类型码
(2)pushf
(3)TF = 0 和IF = 0
(4)push CS
(5)push ip
(6)(IP) = (N * 4) CS = (N * 4 + 2)

12.5节   中断处理程序和iret指令

由于CPU随时都要检测中断信息,所以中断处理程序必须一直存储在内存的某段空间中

中断处理程序的编写过程
(1)保存中断过程用到的寄存器
(2)处理中断
(3)恢复用到的寄存器
(4)用iret指令

iret指令用汇编描述为:
pop IP
pop CS
popf

由可以看出入栈时必须是先pushf,然后push CS,最后到IP

12.7节~12.10节编程处理0号中断

按照书里面的套路就是:
(1)首先将中断的程序代码移动到0000:0200H处(利用movsv命令)
(2)然后将中断程序写出来(就是在屏幕显示字符的程序)
(3)注意将要显示的字符串放在0000:0200H处,这是因为数据段的信息会因为程序的结束而释放掉,然后被别的信息覆盖
但在0000:0200H的中断代码却一直保留着,因为中断是一直在监听的,当再次发生中断时,将显示字符串的不是你想要的信息。
故要将数据段的内容放在一段安全的地方
(4)最后就是修改中断向量表了

这里放上完成的代码(亲测可行哦)

assume cs: code

code segment

start:         mov ax, cs
                        mov ds, ax
                        mov si, offset do0
                       
                        mov ax, 0
                        mov es, ax
                        mov di, 200H
                       
                        mov cx, offset do0end-offset do0
                       
                        cld
                        rep movsb
                       
                        mov ax, 0
                        mov es, ax
                        mov word ptr es:,200H
                        mov word ptr es:, 0
                       
                        mov ax, 4c00H
                        int 21H
                       
                       
        do0:        jmp short do0start
                        db "overflow!"
                       
do0start:        mov ax, cs
                                mov ds, ax
                                mov si, 202H
                               
                                mov ax, 0b800H
                                mov es, ax
                                mov di, 12*160+72
                               
                                mov cx, 9
                        s: mov al,
                                mov es:, al
                                inc si
                                add di, 2
                               
                                loop s
                               
                                mov ax, 4c00H
                                int 21H
                       
do0end:        nop
code ends
end start
                       

12.11节   单步中断

单步中断的类型码是:1

当TF标志位为1的时候将引发单步中断

debug每次执行完t时将显示寄存器的信息,利用的就是单步中断

为了不让单步中断陷入单步中断的死循环,每次单步中断之前都将TF为设置为0,我猜想其他中断也是要如此吧^_^


12.12节   响应中断的特殊情况

当执行压栈指令时将不引发中断过程,因为压栈过程是连续设置ss和sp的,这时引发中断将引发sp的不一致,从而导致错误

宁静致远苏铭 发表于 2017-12-2 21:10:15

问一下
30.do0start:      mov ax, cs
31                              mov ds, ax
32                              mov si, 202H
第32行为何默认ds是0,直接取si为202H
ds为何不能选择其他值,例如0020,si:0
{:5_94:}

若余相思 发表于 2017-12-3 00:46:24

宁静致远苏铭 发表于 2017-12-2 21:10
问一下
30.do0start:      mov ax, cs
31                              mov ds, ax


你想一下,我的中断处理程序在0:200h处,我的CS和IP就要分别是0和200H
我的字符串overflow!在段地址为0,偏移地址为202H处,所以ds只能置为0,si只能置为202H啊
如果取了你写的值,那指向就不是overflow!了 ^_^
页: [1]
查看完整版本: 第十二章 内中断