首先中断分为3类:

  1. 中断,叫这个名纯粹是因为起不了别的名字而已,我们只需要知道第一类中断产生的原因以及含义即可。英文名叫 interrupt,这类中断由外部设备产生,比如键盘、鼠标等。比如,当我们敲击键盘时,键盘会给 CPU 和外设中间的设备 可编程中断控制器 发送一个脉冲信号,可编程中断控制器会根据是哪个引脚接收信号来映射出一个中断号,将这个中断号存储在与CPU连接的端口上,然后可编程中断控制器会向 CPU 发送一个信号,CPU 每次在执行完一条指令后都会检查是否由中断信号需要处理。检测到有外部中断需要处理,它就会去刚刚那个端口读取到这个中断号的值。然后做出相应的处理
  2. 异常,英文名叫 exception,由 CPU 在执行指令时发现有问题时产生一类中断,比如除0异常、错误指令异常、缺页异常等。这些异常都对应一个中断号,CPU内部有自己排线逻辑去接收这个中断号,然后做出相应的处理
  3. INT 指令,这个应该很好理解,这是我们自己写在指令当中的,CPU接收到中断号就会像执行函数一样,CPU会跳转到对应的地方做出相应的处理

它们虽然产生的方式不同,但是殊途同归,都会让CPU放下手中的活,先去执行对应的类似函数一样的一系列指令,然后再回来继续执行之前被打断的地方

那 CPU 收到中断号后,如何处理呢?

先用一句不太准确的话总结,CPU 收到一个中断号 n 后,会去中断向量表中寻找第 n 个中断描述符,从中断描述符中找到中断处理程序的地址,然后跳过去执行

具体的又要涉及到段选择子、段描述符、逻辑地址、线性地址和最终的物理地址,这里不多做解释

具体看认认真真的聊聊中断这篇文章

在执行中断代码前,CPU 主要做了这些事,主要是压栈操作

1. 如果发生了特权级转移,压入之前的堆栈段寄存器 SS 及栈顶指针 ESP 保存到栈中,并将堆栈切换为 TSS 中的堆栈。

2. 压入标志寄存器 EFLAGS。

3. 压入之前的代码段寄存器 CS 和指令寄存器 EIP,相当于压入返回地址。

4. 如果此中断有错误码的,压入错误码 ERROR_CODE

5. 结束(之后就跳转到中断程序了)

之后的栈变成了这样子

低地址
ERROR_CODE(异常错误码) $<—— 堆栈指针 SS:ESP$
EIP(中断发生前的指令寄存器)
CS(中断发生前的代码段)
EFLAGS(标志寄存器)
ESP(中断发生前的栈顶指针)
高地址