CPU的中断(汇编)

内中断

中断源 : 中断类型码N(8位) –>N号中断向量–>中断向量表(内存0000:0~0000:03FF,每项两个字,放中断处理程序的入口地址,即段地址(4N)+偏移地址(4N+2))
除法错误(溢出) : 0
单步执行 : 1 –>每执行一条指令后,都检查TF=1则中断
执行into指令 : 4
执行int指令 : int n –>引发n号中断

中断过程:
1.取得中断码
2.保存标志寄存器
3.设置标志寄存器的8位TF=0,9位IF=0防止CPU在执行中断时发生单步中断
4.保存CS和IP(用于返回)
5.取得入口地址,设置IP(中断类型码*4)和CS(中断类型码*4+2)的值
6.硬件自动完成中断


编程处理除法中断(0)
功能:发生中断时在屏幕中间显示“overflow!”
1、0000:0200~0000:02FF的256个字节的空间是空的,写入中断程序;
2、入口地址(偏移地址)=0*4,段地址=0*4+2,将入口地址放入中断向量表。

assume cs:code
code segment

start://将中断程序写入一块空地方
      mov ax,cs         //设置ds:si指向原地址
      mov ds,ax
      mov si,offset do0

      mov ax,0          //设置es:di指向要写入的地址0000:0200
      mov es,ax
      mov di,200h

      mov cx,offset do0end-offset do0  //传输长度
      cld                              //传输方向为正
      rep movsb

      //将中断程序的入口地址0:200写入中断向量表项0:0
      mov ax,0                       
      mov es,ax
      mov word ptr es:[0*4],200h
      mov word ptr es:[0*4+2],0

      mov ax,4c00h      
      int 21h


do0:jmp short do0start     //在程序中分一块空间存放数据“overflow!”防止被覆盖
    db "overflow!"

do0start:mov ax,cs      //设置ds:si指向字符串,“overflow!”的地址为0:202
         mov ds,ax
         mov si,202h

    mov ax,0b800h      //设置es:di指向显存的中间位置
    mov es,ax
    mov di,12*160+36*2

    mov cx,9          //循环,显示字符串
  s:mov al,[si]       
    mov es:[di],al
    inc si
    add di,2
    loop s 

    mov ax,4c00h      
    int 21h
 do0end:nop

code ends
end start

编程处理int n调用中断
(int指令:保存标志寄存器、CS、IP入栈 ,配合 iret指令:出栈IP、CS、标志寄存器 )
(分两个程序,一个程序调用中断,一个程序安装中断)
功能:用int 7ch中断例程完成LOOP指令

//调用中断的程序
assume cs:code
code segment

start:mov bx,offset s-offset se //bx保存转移地址,在两个程序间传递
      mov cx,80
    s:...(循环体)
      int 7ch  //调用7ch处中断程序
    se:nop(只是起标记作用)

mov ax,4c00h
int 21h
//安装中断到7ch处
...(将中断写入一块空地)
...(将中断程序的入口点写入中断向量表项0:7ch)
lp:push bp
   mov bp,sp
   dec,cx
   jcxz lpret
   add [bp+2],bx
lpret:pop bp
      iret

引发7ch中断,保存CS和IP入栈(CS的值=s的段地址;IP的值=se的偏移地址)–>进入lp,第一句push bp
这时栈中的情况如下图:
这里写图片描述
继续执行:
mov bp,sp–>bp指向栈顶,
add [bp+2],bx–>bp+2指向se的偏移地址,bx=s-se,所以se+s-se=s,将bp+2处修改成了s的偏移地址
iret出栈IP和CS,从标号s处开始执行指令

int n调用系统提供的中断例程
BIOS(基本输入输出系统,在系统板的ROM中):包含I/O操作的中断例程,一个包含多个子程序(用ah选择子程序的编号)
DOS(操作系统):也有中断例程–>mov ax,4c00h int 21h(调用第21h号中断例程的4ch号子程序)

外中断

分类:
1.可屏蔽中断。若IF=1,则CPU执行完当前指令后,相应中断。若IF=0,则不响应。
2.不可屏蔽中断。中断类型码为2。


编写int 9中断例程(处理键盘输入,键盘有操作就引发int 9中断)
1.按下一个键,对应一个通码;放开一个键,对应一个断码。断码=通码+80h
2.通码或断码–>60端口–>BIOS引发9号中断–>扫描码(通码/断码)+字符码(a~z)写入键盘缓冲区,状态字节(shift、ctrl等)写入状态内存区
3.用别的指令模拟int指令的中断过程

1.取得中断码
2.保存标志寄存器   
pushf
3.设置标志寄存器的TF=09位IF=0
        pop ax
        and ah,11111100b  //标志寄存器的第9位和第8push ax
        popf
4.保存CS和IP(用于返回)
5.取得入口地址,设置IP(中断类型码*4)和CS(中断类型码*4+2)的值
        call dword ptr ds:[0]
6.硬件自动完成中断

功能:在屏幕中间依次显示a~z,在显示过程中,按下esc后,改变显示的颜色
分析:改变了esc键对应的功能,也就是改变了int9中断

assume cs:code

stack segment
   db 128 dup (0)
stack ends

data segment  //用来保存原入口地址
   dw 0,0
data ends

code segment
start:mov ax,stack
      mov ss,ax
      mov sp,128

      **********************************************************
      保存int9原入口地址,在中断向量表中写入本int9中断的入口地址           *
      mov ax,data                                              *
      mov ds,ax
                                                               *
      mov ax,0                                                 *
      mov es,ax
                                                               *
      push es:[9*4]                                            *
      pop ds:[0]                                               *
      push es:[9*4+2]                                          *
      pop ds:[2]                                               *
                                                               *
      mov word ptr es:[9*4],offset int9                        *
      mov es:[9*4+2],cs                                        *
      ***********************************************************

     //在屏幕上依次显示a~z
      mov ax,0b800h
      mov es,ax
      mov ah,'a'

    s:mov es:[160*12+40*2],ah
      call delay
      inc ah
      cmp ah,'z'
      jna s

      ********************************************************
      恢复int9原入口地址,恢复键盘的功能
      mov ax,0
      mov es,ax
      push ds:[0]
      pop es:[9*4]
      push ds:[2]
      pop es:[9*4+2]
      *********************************************************

      mov ax,4c00h
      int 21h

      //循环延时。空循环100000h次,为了延长字母显示的时间
delay:push ax
      push dx
      mov dx,10h//高8mov ax,0//低8位
   s1:sub ax,1
      sbb dx,1
      cmp ax,0
      jne s1
      cmp dx,0
      jne s1
      pop dx
      pop ax
      ret

      //按下esc键变颜色
 int9:push ax
      push bx
      push es

      in al,60h(从60端口读入键盘的输入)

      pushf(模拟调用int9中断)
      pushf
      pop bx
      and bh,11111100b
      push bx
      popf
      call dword ptr ds:[0]

      cmp al,1(判断是否按下了esc键,esc键的通码为1)
      jne int9ret

      mov ax,0b800h
      mov es,ax
      inc byte ptr es:[160*12+40*2+1](字符的属性,改变数值则变颜色)

int9ret:pop es
       pop bx
       pop ax
       iret

code ends
end start

编写int 16h中断例程(读取键盘缓冲区)
引发int 16h中断–>读取键盘缓冲区第一个字单元–>扫描码(高8位)送入ah,字符码(低8位)送入al–>已经读取的从缓冲区删除–>循环(若缓冲区空,则等待)
功能:
1.字符串输入,同时显示在屏幕上;能删除已有的字符(用栈存字符串)
2.输入回车后,结束输入(输入回车时在字符串上加0)
字符串输入

用int 13h中断例程(读写磁盘)
给出面号(0~n)、磁道号(0~n)、扇区号(1~n)

读取0面0道1扇区的内容

mov al,1(读取的扇区数量)
mov ch,0(磁道号)
mov cl,1(扇区号)
mov dl,0(驱动器号,软盘从0开始,硬盘从80h开始)
mov dh,0(磁头号,软盘即面号)
mov ah,22表示读取,3表示写入)
int 13h
读取成功,ah=0;读取失败,ah=出错代码
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值