一、什么是中断
中断是打断CPU正常的指令执行顺序转而去执行位置的指令的行为。非常类似于CPU不听使唤的执行了一个CALL指令的样子。
中断主要由三部分组成,中断号 、中断向量表、中断程序程序。
中断号指明要去执行什么程序,
中断向量表表明这个程序存放的位置。
中断向量表存放在内存开始处,即地址为 0的地方,中断向量表每一项包含4字节,前两字节是偏移地址,后两字节是段地址,共256个中断向量,所以中断向量表占用内存为1K。
所以假设触发了中断号是 N的中断,那么在中断向量表偏移地址N*4的位置就存储着处理这个中断的程序的地址。
所以实际上完全可以通过修改中断向量表来实现自己的中断处理程序。
中断的产生有三种
1. CPU内部错误(除0等等,不可屏蔽)
2. 硬件中断( 硬件错误或者外围硬件事件,比如键盘事件, 硬件错误为不可屏蔽中断,其余一般都是可屏蔽中断)
3. 软件中断( 使用int 指令触发中断,或者使用标志寄存器的调试标记未,不可屏蔽)
注意:
中断有优先级:内部中断 > 硬件非屏蔽中断 > 硬件可屏蔽中断 > 内部的调试中断
中断是可以嵌套调用的
中断发生时,CPU 会将 FLAGS CS IP 三个寄存器一次压栈,如果中断返回使用 IRET 进行反向操作( CPU是直接使用当前正在运行的程序的堆栈?那硬件中断也是随机借用?如果堆栈满了会怎么样? )
二、INT 中断
INT 中断是固化在主板的ROM中的BIOS系统提供的用于代码和硬件交互的程序集合,其实将 INT触发的软中断理解成主板(BIOS)提供的API函数即可,实际上它和call指令也没啥区别,只不过call指令跟的是地址int指令跟的是中断编号,cpu自动将中断编号对照中断表转换成指定的中断例程地址。
所以接下来就来介绍一下常用的一些系统服务,这些服务程序都是写在主板的ROM中是基本输入输出系统BOIS的一部分,在启动的时候由BOIS设置到INT向量表中为程序提供基本的操作支持。
基本调用方法
以前提到过调用函数时传递参数的方式,INT 中断采用的是寄存器传参的方式,所以调用之前需要根据功能给不同的寄存器赋相应的参数(不同指令用到寄存器和对应的作用可能都不相同)然后运行相应的int指令,基本样式如下:
mov al,xxx
mov ah,xxx
mov bl,xxx
mov bh,xxx
int xxx
键盘输入
键盘输入是硬件中断,一般安排的中断号是9H,9H中断处理程序会根据键盘的输入内容,缓存15个值,存放在 0040:001E ~ 0040:003D 之间,这个是循环缓冲区 0040:001A 存放起始位置,0040:001C 存放结束位置,所以如果这两个值相等表示缓冲区为空,其他一些标志位存放在 0040:0017 内存中,比如shift 键 和 大小写键的状态。
BIOS 也提供了 16H中断来 方便程序提取输入内容
功能如下
功能号 输入内容
AH = 00H AL=输入字符的ASCII码
AH= 字符的扫描码
AH = 01H ZF = 1表示无键可读
ZF = 0 表示有键可读
AH = 02H AL = 安装状态(shift 大小写, 以及其他)
AH = 10H 同AH = 0H
AH = 11H 同AH = 1H
例子:
wait: mov ah, 1 ; 设置功能号1 用于测试是否有字符可读
int 16h ; 调用16号中断
jnz wait ; 返回返回的结果ZF标志位,如果没有可读的内容就继续判断
mov ah, 0 ; 否则设置功能号 为0 来读取内容
int 16h ; 调用16号中断取内容
显示输出
先是有几种模式,这里介绍介绍3号文本先是模式,在这种模式下显示器被分为 80列 25行,一共能显示1000个字符
从B800:0000 或者 B000:0000 位置开始就是显示存储区域,屏幕的每个字符占2个字节的内存,第一个自己的内存表示要显示字符的ASCII值,第二个字节表示属性,属性包括 前景色 背景色 闪烁等内容,如果内存排列如下
(0,0) (0,1) (0,2) (0,3 )
[ASCII码][属性] [ASCII码][属性] [ASCII码][属性] [ASCII码][属性]
其中属性字节每一位的定义如下
[7] [6][5][4] [3] [2][1][0]
闪烁 背景 亮度 前景
由于颜色一种只有3位,所以能表示的颜色只有8种,前景色还有个亮度,所以前景色一个有16种。
BIOS 提供的中断号是 10H 中断
详细介绍如下: https://blog.csdn.net/gaoxionghao/article/details/23539039