CPU是怎么检测到外中断的?

王爽-汇编语言

CPU正在执行指令呢 , 怎么就检测到中断信息了 ? 这里怎么检测到的得说清楚啊喂~

clipboard.png

  1. 这里的芯片是什么 , 是和CPU一样具有运算能力的硬件吗?

  2. 芯片 (键盘上的) 将扫描码送到相关芯片 (主板上的) 的寄存器中 , 然后CPU是怎么得到这个扫描码的呢 ?

以下是我的想法 :
如果这里指的芯片是和CPU差不多的硬件 (上面说到他可以操作IO , 送数据到相应的空间),
那么我有两种设想 :

  1. CPU指定一块空间交给主板上的芯片来读写 , 在外部设备想要让CPU触发某些中断的时候就通过主板上相应的接口芯片往这块空间写数据 . 然后CPU会每隔一段时间去读这个空间的数据来判断需不需要响应这个中断 .

  2. CPU每隔一段时间去读主板上各个接口芯片的寄存器来判断是否需要触发某些中断

最近在看王爽老师的汇编语言 , 其他地方都挺详细啊 , 这里讲的稍微有点模糊...

阅读 15k
3 个回答

如果要说清楚:

CPU正在执行指令呢 , 怎么就检测到中断信息了 ? 这里怎么检测到的得说清楚啊喂~
就要从数电说起,所以不太可能很简单的就说清楚。

CPU 就是一个很大的时序电路,通过外部的管脚与其他的设备相互链接。比如 8086的引脚图

图片描述

通过这些管脚我们可以控制 CPU 的行为,其中有写管脚有多种功能,这是为了节省管脚而设计的,所以需要额外的电路(芯片叫集成电路,就是把很复杂的电路集成到很小的一个芯片里)把这个复用的管脚分开或是只用其中的一种功能。

因为CPU 比较复杂,因此我们发明了上面的一些概念帮帮助我们记忆和理解CPU的行为。如何控制各个管脚从内存和外设中读写数据,是我们学习汇编不需要的,因此汇编的书中不会讲。《微机原理》倒是会讲,可是很简略,没有数电的基础不一定能看懂。
AD0~AD15是地址线和数据线复用,所有设备发送的数据都连接到D0~D15上,CPU通过A0~A19 D0~D15(通过外部电路把AD0~AD15分成两个) 从内存和外设读写数据,分别叫做地址总线和数据总线。总线其实就一组管脚。CPU通过M/IO告诉外界读取内存还是外设的数据。CPU通过这么几根管脚表明自己要读写的外设或是内存地址,所以还是需要比较复杂的外部电路去帮助CPU控制各个外设的不会同时把数据发送到数据总线上。读取外设的时候,外部电路通过地址总线上的值,确定CPU要读写哪个设备,控制对应的设备链接到数据总线上。一个设备能不能给CPU发送数据完全是 CPU 说了算的。可以说所有的外设都会有管脚链接到数据总线(当然有些设备没有那么多发送数据的管教)。

外设是否能发送数据,完全由CPU说了算,CPU如何检测外设是否有数据有两种方案可选,第一,自己写代码,执行完一段代码之后去检查每一个外设看看这个外设是否有数据要读写。这在很多嵌入式编程中也比较常见。第二,就是外设有数据要读写的时候,给CPU的某个管脚发送数据,让CPU知道之后,主动来读写这个外设。这就是中断,这是几乎所有处理器都会提供的功能。

可以看到,CPU管脚上有两个管脚叫做 NMI INTR对应不可屏蔽和可屏蔽中断。CPU在执行完一条指令之后就会检测这个管脚的状态,如果满足某个条件就不再执行下一条指令,而是做另外一件事情,这件事情就是中断处理那一套过程。这就是外部中断。当CPU执行完一条指令,比如指令执行出错了,CPU也会进行另外的处理,这就是内部的终端。这是CPU内部电路的设计,不是简单的能说清楚如何设计的时序电路。Intel的设计就是这样的,但是其他的处理器可能就不是这样设计的。

简单来说,如今学习汇编的这些操作,都是建立在已经搭建好的固定的电路图的基础上来说的,所以像给键盘分配了 60h 64h 的地址都是当年这样设计的电路。在嵌入式的编程中由于要自己搭建电路,不一定总要键盘。这时使用不同的外设是你自己分配的地址(主要看你如何搭建连接CPU的引脚,当然在那里面一般不叫CPU)。

现在我们只有一个外部可屏蔽中断的管脚,可是外设那么多不可能所以外设都链接到这一个管脚上呀,否则CPU怎么区分是谁发出的信号。这就有了 8259, 8259 有多个管脚就是像INTR一样接收中断的,然后把8259 连接到 CPU 的INTR上,这样,当发生中断 CPU 就知道只可能是 8259 发送来的,所以就会去询问 8259,而不同的外设链接到8259 不同的管脚上,8259 就可以通过管脚来确定是哪个是那个外设发送过了的。当CPU询问的时候他就可以通过数据先告诉CPU是哪个外设发送来的中断(其实是中断向量号,可是自己设置,但是设置为与内部中断冲突就不好了,其实BIOS初始化到其中的值就与内部中断冲突)。所以外设想要发送一个中断就把链接到 8259 上的那个管脚置为低电平。

其实键盘不是直接链接到数据总线上,而是链接到 8042 上,8042 才有管脚链接到数据总线上,其实你说的对,这些芯片都是像CPU那样的东西,只是功能比较单一只能做某些固定的事情(所以比较便宜和简单,基本只要知道其管脚的功能和内部几个寄存器的功能就算是学会了使用这个芯片)。键盘中的芯片8048 就是简单的根据你按下和松开某个按键,通过管脚给 8042 发送对应的数值。8042 再通过总线把 8048 发送来的额数据发送给 CPU。8042其实有引脚链接到8259的第二根中断管教上。

在知道找到答案了

CPU对系统内部中断源提出的中断请求必须响应,而且自动取得中断服务子程序的入口地址,执行中断 服务子程序。对于外部中断,CPU在执行当前指令的最后一个时钟周期去查询INTR引脚,若查询到中断请求信号有效,同时在系统开中断(即IF=1)的情 况下,CPU向发出中断请求的外设回送一个低电平有效的中断应答信号,作为对中断请求INTR的应答,系统自动进入中断响应周期。

原来CPU每执行一条指令还要去中断引脚检查一遍有没有中断请求哈~


以下是原文

一般中断处理的主要步骤分别是中断请求、中断判优、中断响应、中断处理和中断返回。

在微机系统中,对于外部中断,中断请求信号是由外部设备产生,并施加到CPU的NMI或INTR引脚上,CPU通过不断地检测NMI和INTR引脚信号来识 别是否有中断请求发生。对于内部中断,中断请求方式不需要外部施加信号激发,而是通过内部中断控制逻辑去调用。无论是外部中断还是内部中断,中断处理过程 都要经历以下步骤: 请求中断→响应中断→关闭中断→保留断点→中断源识别→保护现场→中断服务子程序→恢复现场→中断返回。

请求中断
当某一中断源需要CPU为其进行中断服务时,就输出中断请求信号,使中断控制系统的中断请求触发器置位,向CPU请求中断。系统要求中断请求信号一直保持到CPU对其进行中断响应为止。

中断响应
CPU对系统内部中断源提出的中断请求必须响应,而且自动取得中断服务子程序的入口地址,执行中断 服务子程序。对于外部中断,CPU在执行当前指令的最后一个时钟周期去查询INTR引脚,若查询到中断请求信号有效,同时在系统开中断(即IF=1)的情 况下,CPU向发出中断请求的外设回送一个低电平有效的中断应答信号,作为对中断请求INTR的应答,系统自动进入中断响应周期。

关闭中断
CPU响应中断后,输出中断响应信号,自动将状态标志寄存器FR或EFR的内容压入堆栈保护起来,然后将FR或EFR中的中断标志位IF与陷阱标志位TF清零,从而自动关闭外部硬件中断。因为CPU刚进入中断时要保护现场,主要涉及堆栈操作,此时不能再响应中断,否则将造成系统混乱。

保护断点
保护断点就是将CS和IP/EIP的当前内容压入堆栈保存,以便中断处理完毕后能返回被中断的原程序继续执行,这一过程也是由CPU自动完成。

中断源识别
当系统中有多个中断源时,一旦有中断请求,CPU必须确定是哪一个中断源提出的中断请求,并由中断控制器给出中断服务子程序的入口地址,装入CS与IP/EIP两个寄存器。CPU转入相应的中断服务子程序开始执行。

保护现场
主程序和中断服务子程序都要使用CPU内部寄存器等资源,为使中断处理程序不破坏主程序中寄存器的内容,应先将断点处各寄存器的内容压入堆栈保护起来,再进入的中断处理。现场保护是由用户使用PUSH指令来实现的。

中断服务
中断服务是执行中断的主体部分,不同的中断请求,有各自不同的中断服务内容,需要根据中断源所要完成的功能,事先编写相应的中断服务子程序存入内存,等待中断请求响应后调用执行。

恢复现场
当中断处理完毕后,用户通过POP指令将保存在堆栈中的各个寄存器的内容弹出,即恢复主程序断点处寄存器的原值。

中断返回
在中断服务子程序的最后要安排一条中断返回指令IRET,执行该指令,系统自动将堆栈内保存的 IP/EIP和CS值弹出,从而恢复主程序断点处的地址值,同时还自动恢复标志寄存器FR或EFR的内容,使CPU转到被中断的程序中继续执行。

clipboard.png

简单的理解,cpu的中断 就像电灯的开关,是个硬件线路的设计。只是中断比开关复杂得多。

外部硬件通过cpu的中断引脚给cpu发出中断请求

cpu暂停当前任务,保存各个寄存器状态,

cpu根据中断号去执行中断例程,处理完中断事件;

cpu恢复原来保存的寄存器状态,继续执行原先的任务。


大概就是这样

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏