zoukankan      html  css  js  c++  java
  • 汇编学习笔记(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!

  • 相关阅读:
    作业12:字典dict讲解及增删改查等操作
    作业11:元祖及元祖的嵌套
    作业10:列表的嵌套
    作业09:列表的增删改查
    什么数据类型
    作业08:字符串操作
    Visual Studio Code 写Python 代码
    Python——面向对象(初级篇)
    Python 学习第三部分函数——第一章函数基础
    Python3 字典
  • 原文地址:https://www.cnblogs.com/michaelle/p/4023325.html
Copyright © 2011-2022 走看看