汇编学习12 内中断

1.内中断产生

  • CPU产生内中断的原因:
    (1)除法发生溢出
    (2)单步执行指令
    (3)执行into指令(?)
    (4)执行int指令
  • 每一种中断都对应中断类型码,来标识中断信息的来源。
    除法溢出:0;单步执行:1;into指令:4;int+N 指令:立即数N标识中断源
  • 中断向量表和中断处理程序
    中断处理程序是指的当CPU收到中断号以后,会转而执行该中断信息的处理程序。一般来说不同的中断信息有不同的中断处理程序。
    中断向量表指的是存储中断向量的列表,也就是中断处理程序的入口地址表(里面存储'中断号->中断处理程序入口地址)。每当中断发生,CPU会根据中断号到这个表里面去寻找相应处理程序的入口地址。

补充说明:
中断向量表存放在内存地址:0000:0000~0000:03FF位置;
中断号0对应的处理程序地址放在内存地址0处,一个表项占两个字,高地址字存放段地址,低地址字存放段偏移地址;
所以以此类推,中断号1对应处理程序入口地址存放在内存地址4X1处;中断号2程序入口地址在4X2处......

2.中断过程

  • 中断过程经历的6个步骤:
    (1)从中断信息中取得中断类型码
    (2)标志寄存器入栈(中断过程中要改变标志寄存器的值,所以要先保存现场)
    (3)设置标志寄存器的第八位TF和第九位IF的值为0
    (4)CS的值入栈
    (5)IP的值入栈(IP值在栈顶)
    (6)从中断向量表中读取中断程序的CS和IP值并修改当前值

  • 编写中断处理程序的步骤:
    (1)保存要用到的寄存器的值
    (2)处理中断
    (3)恢复寄存器的值
    (4)用iret指令返回(iret指令是指的,将中断前的IP和CS,和标志寄存器相继出栈,返回原来位置)

3.相应中断的特殊情况

我们知道在Dos 的debug模式下,我们执行命令-t,可以实现单步调试。而Debug怎样让CPU做到单步调试呢?实际上这就是利用单步中断的结果。

  • Debug的-t指令原理:在每一次用-t命令执行指令的时候,Debug将标志位TF置为1,使得CPU工作于单步中断模式下,执行完每条指令后就引发单步中断,然后执行中断程序将所有寄存器的内容显示在屏幕上。

  • 特殊情况:当CPU执行完向SS寄存器传送数据的指令后,即便是发生中断,CPU也不会响应。(因为在执行完向SS传送数据的指令后,已经修改了栈段的位置,下一步应该要修改栈顶指针SP的值,如果在修改了SS后,没来得及修改SP就引发了中断将造成栈的位置错误),所以在Debug模式中要等到SS和SP全部修改完成后才会相应中断。

本章实验要求:

重新改写0号中断(除法溢出),让程序在发生溢出的时候,在屏幕中央输出‘divide error!’,并返回DOS

  • 实验补充:
    div指令可以进行除数为8位的除法和16位的除法,除数可以放在一个reg或者内存单元中
    (1)当除数为8位的时候:被除数为16位,放在AX中;计算出的结果,商放在AL中,余数放在AH中
    (2)当除数为16位的时候:被除数为32位,高位放在DX中,低位放在AX中;计算出来的结果,AX存储商,DX存储余数

实验示例代码:

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 ; do0代码段的长度
    cld
    rep movsb ; 串传送指令

    mov ax,0
    mov es,ax
    mov word ptr es:[0],200H
    mov word ptr es:[2],0 ; 重新设置中断向量表的中断跳转地址

    mov ax,1000H ; 尝试执行除法溢出
    mov bh,1
    div bh

    mov ax,4c00H
    int 21H

do0:jmp short do0start
    db "divide error!"
    
do0start:   
    mov ax,0B800H
    mov ds,ax
    mov si,12*160+36*2; 设置显存的地址为目的地址
    mov ax,0
    mov es,ax
    mov di,202H ; 设置db分配的字符串位置为源地址(jmp short指令长度为2)

    mov cx,13
S:  mov al,es:[di]
    mov ds:[si],al
    mov al,02H ; 设置字体样式颜色
    mov ds:[si+1],al
    add si,2
    inc di
    loop S; 循环,将源地址字符串送到显存

    mov ax,4c00H
    int 21H
do0end: nop

code ends
end start

执行结果如下图所示:


汇编学习12 内中断_第1张图片
123.GIF

实验总结:
要修改中断处理程序,我们要考虑以下问题:
(1)我们首先要想到我们要将这段程序存放在内存里,CPU在中断向量表中寻找的时候才能找得到,那么放在哪里呢?一般来说,我们可以告诉操作系统,让操作系统给我们分配空余位置。但是在本次实验中,我们可以取内存0000:0200~0000:02FF(这一段在中断表中,但是却不存放任何表项)这256个空的字节单元作为存储中断程序的区域。
(2)怎样传过去?我们可以用串传送指令movsb将程序段直接传到指定的内存位置。
(3)用串传送,我们怎么知道处理程序有多大?我们不需要直到有多大,直接用程序段开始和程序段结束的偏移位置相减即可
(4)怎样修改中断向量表呢?放好了中断处理程序,我们就要使中断表中对应的中断号对应的入口地址发生改变。中断表放在0000:0000~0000:03FF位置,我们根据相应中断号N,内存位置0000:4xN存放的是段偏移地址,0000:4xN+2存放的是程序段位置。

你可能感兴趣的:(汇编学习12 内中断)