java打印对象内存地址 分布式事务 事务消息 分布式事务 几种解决方案 分布式事务-Seata 分布式事务-Seata 分布式事务-LCN-TCC 分布式事务-LCN 分布式事务-消息队列-定时任务-本地事件表 Zuul网关实战02 Zuul网关实战01 灰度发布落地实战2 灰度发布落地实战1 Gsnova on Heroku build Systemd Debian system initialization manage multi id_rsa ubuntu 64bits cannot run 32bits app REHL power auditing Debug Assembly for ARMv8 on QEMU ARM体系结构--寄存器 Run Debian iso on QEMU ARMv8 QEMU ARM64 guide cross compiler install buildroot install QEMU install python入门--数据结构 python入门--内置数据类型 python入门--类 异常 python入门--条件表达式 方法 python入门--数字 字符串 数组 RTC驱动分析 块设备驱动 TCP UDP socket 触摸屏驱动 USB驱动 LED按键中断 LCD 驱动 驱动信号 根文件系统 实验 内核实验 字符设备驱动程序 绪论 uboot 实验 LCD 实验 系统时钟和UART 中断控制器 Nand Flash控制器 MMU 实验 储存管理器实验 GPIO实验 点亮LED 编译加载驱动 制作烧写内核 dnw替代方法 MINI2440 TQ2440安装配套Linux 使用NFS 制作烧写跟文件系统 grub引导Windows 烧写裸版程序-linux Ubuntu 网络没有 eth0 Linux自动挂载 烧写裸板程序 电路基础 Mac词典 Vim插件 Assembly 综合研究 Assembly 指令总结 Assembly 直接定址表 Assembly 使用BIOS进行键盘输入和磁盘读写 Assembly 外中断 Assembly 端口 Assembly int指令 Assembly 内中断 Assembly 标志寄存器 Assembly 转移指令的原理 Assembly Call和ret指令 Assembly 数据处理两个基本问题 Assembly 灵活定位内存地址 Assembly 包含多个段的程序 Assembly [bx] loop Assembly 第一个程序 Assembly 寄存器 (内存访问) Assembly 寄存器 AWS VPN with EC2 hidden file in picture(linux) Assembly 基础 idea shortcuts 常用快捷键 idea plugin folder install ruby and jekyll

Assembly 内中断

2014年09月28日

任何一个通用的CPU,比如8086,都具备一种能力,可以在执行完当前正在执行的指令之后,检测从CPU外部发送过来的或内部产生的一种特殊信息,并且可以立即对所接收到的信息进行处理,这种特殊的信息,成为中断信息


中断信息可以来自CPU内部和外部


###内中断的产生 对于8086CPU,当CPU内部有下面的情况发生的时候,将产生中断信息:

  1. 除法错误,比如,执行div指令产生的除法溢出
  2. 单步执行
  3. 执行into指令
  4. 执行int指令

他们是不同的信息,要进行不同的处理

中断信息中,必须包含识别来源的编码。8086CPU用称为中断类型码的数据来标识中断信息的来源。中断类型码为一个字节型数据,可以表示256种中断信息的来源,称为中断源

上述的4种中断源,在8086CPU中的中断类型码如下:

  1. 除法错误:0
  2. 单步执行:1
  3. 执行into指令:4
  4. 执行int指令,该指令的格式为int n,指令中的 n 为字节型立即数,是提供给CPU的中断类型码

###中断处理程序 CPU收到中断信息后,需要对中断信息进行处理,如何处理?可以由我们编程决定,需要针对不同的中断,编写不同的中断处理程序

中断类型码的作用就是用来定位中断处理程序

###中断向量表 即:中断处理程序的入口地址列表,在内存中保存,共存放256个中断源所对应的中断处理程序的入口

对于8086PC机,中断向量表指定放在内存地址0

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

对于8086CPU,这个入口地址包括段地址和偏移地址,所以一个表项占两个字(dword 4Byte),高地址字存放段地址,低地址字存放偏移地址

存储在N号中断源对应的中断处理程序入口的偏移地址的内存单元的地址为:4N,段地址为4N+2

###中断过程 用中断类型码找到中断向量,并用它设置CS和IP,这个工作是由CPU的硬件自动完成的,这个工作的过程称为中断过程

CPU收到中断信息后,要对中断信息进行处理,首先将引发中断过程。硬件在完成中断过程后。CS:IP将指向中断处理程序的入口,CPU开始执行中断处理程序

8086CPU在收到中断信息后,所引发的中断过程:(程序员无法改变)

  1. (从中断信息中)取得中断类型码
  2. 标志寄存器的值入栈(因为在中断过程中药改变标志寄存器的值,所以先将其保存在栈中)
  3. 设置标志寄存器的第8位TF和第9位IF的值为0(外中断内容中将介绍)
  4. CS的内容入栈
  5. IP的内容入栈
  6. 从内存地址为中断类型码4,和中断类型码4+2 的两个字单元中读取中断处理程序的入口地址设置IP和CS

简洁的描述中断过程,如下:

  1. 取得中断类型码N
  2. pushf
  3. TF=0,IF=0
  4. push CS
  5. push IP
  6. (IP)=(N * 4),(CS)=(N * 4 + 2)

在最后一步完成后,CPU开始执行由程序员编写的中断处理程序

###中断处理程序和iret指令 由于CPU随意都可能检测到中断信息,所以中断处理程序必须一致存储在内存某段空间之中

中断处理程序的编写方法和子程序比较相似:

  1. 保存用到的寄存器
  2. 处理中断
  3. 恢复用到的寄存器
  4. 用iret指令返回

iret指令的功能用汇编语法描述为:

pop IP

pop CS

popf

iret通常和硬件自动完成的中断过程配合使用

iret指令执行后,CPU回到执行中断处理程序前的执行点继续执行程序

###除法错误中断的处理

mov ax,1000h
mov bh,1
div bh

执行后终端显示Divide overflow后,返回到操作系统中


前面讲到,内存0000:0000~0000:03FF,大小为1KB的空间是系统存放中断处理程序入口地址的中断向量表。8086支持256个中断,但是实际上,系统中要处理的中断时间远没有达到256个。所以在中断向量表中,有许多单元是空的

中断向量表是PC系统中最重要的内存区,只用来存放中断处理程序的入口地址,DOS系统和其他应用程序都不会随便使用这段空间

一般情况下,从0000:0200至0000:02FF的256个字节的空间所对应的中断向量表项是空的,操作系统和其他应用程序都不占用

###编写处理0号中断(除法错误)

  1. 编写可以显示 “overflow!” 的中断处理程序:do0
  2. 将do0送入内存 0000:0200处
  3. 将do0的入口地址0000:0200存储在中断向量表0号表项中

源代码

#####设置中断向量 将do0的入口地址0:200写入中断向量表0号表项中

mov ax,0
mov es,ax
mov word ptr es:[0*4],200h
mov word ptr es:[0*4+2],0

###单步中断(中断类型码为1) 基本上,CPU在执行完一条指令后,如果检测到标志寄存器的TF位为1,则产生单步中断

Debug提供了单步中断的中断处理程序,功能为显示所有寄存器中的内容后等待输入命令。然后,在使用t命令执行指令时,Debug将TF设置为1,使得CPU工作于单步中断方式下

CPU提供单步中断功能的原因就是,为单步跟踪程序的执行过程,提供了实现机制

###响应中断的特殊情况 有些情况下,CPU在执行玩当前指令后,即便是发生中断,CPU也不会响应。

如:在执行完向ss寄存器传送数据的指令后,即便是发生中断,CPU也不会响应,这样做的原因是,ss:sp联合指向栈顶,而对他们的设置应该连续完成(如果不连续执行,执行mov ss,ax后发生中断,标志寄存器压栈,则无法确定sp位置,导致栈数据错误)