中断
首先中断分为3类:
- 中断,叫这个名纯粹是因为起不了别的名字而已,我们只需要知道第一类中断产生的原因以及含义即可。英文名叫 interrupt,这类中断由外部设备产生,比如键盘、鼠标等。比如,当我们敲击键盘时,键盘会给 CPU 和外设中间的设备 可编程中断控制器 发送一个脉冲信号,可编程中断控制器会根据是哪个引脚接收信号来映射出一个中断号,将这个中断号存储在与CPU连接的端口上,然后可编程中断控制器会向 CPU 发送一个信号,CPU 每次在执行完一条指令后都会检查是否由中断信号需要处理。检测到有外部中断需要处理,它就会去刚刚那个端口读取到这个中断号的值。然后做出相应的处理
- 异常,英文名叫 exception,由 CPU 在执行指令时发现有问题时产生一类中断,比如除0异常、错误指令异常、缺页异常等。这些异常都对应一个中断号,CPU内部有自己排线逻辑去接收这个中断号,然后做出相应的处理
- 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(中断发生前的栈顶指针) |
| 高地址 |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 星の夜!
