【问题标题】:Interrupts, Instruction Pointer, and Instruction Queue in 80868086 中的中断、指令指针和指令队列
【发布时间】:2014-05-23 21:13:53
【问题描述】:

假设向 8086 发出外部中断请求。处理器将在完成当前正在执行的指令(如果有)后处理中断。在处理中断之前,程序的状态(PSW 标志、寄存器等)也将通过将数据压入堆栈段来保存。

现在,大多数教程/文档都描述了指令指针也被压入堆栈段,这没关系,因为它指向代码段中的下一个指令字节(就在发出中断请求之前)。

但是指令队列会发生什么?处理中断请求时是否也将其推入堆栈段?还是它的内容被清零了?在这种情况下,指令指针是否应该递减,以便可以使其指向代码段中的先前指令(在中断服务之后)?

这里,中断请求后实际上是指中断请求被处理后。该图显示的是,在中断请求到来之前,指令被缓存,IP指向CS内存段中下一个字节指令的地址。为了处理中断请求,寄存器的内容(包括 IP 和标志)被压入堆栈段。服务请求后,之前的内容被加载回来 - IP 仍然指向第 7 个字节的位置(指令),队列(缓存)为空。这就是我的疑问。 IP 是否递减以指向 i1?其次,我们是否需要手动处理 IP(例如,在中断时将其压入堆栈)还是由中断服务例程为我们处理?请,任何帮助表示赞赏,谢谢!


注意:Instruction Queue - 8086 架构有一个六字节的预取指令流水线。由于执行单元正在执行当前指令,总线接口单元会提前从内存中读取多达六个字节的操作码。

【问题讨论】:

  • (推测,不是事实)管道机制是一个实现细节,而不是 ISA 公开的东西。
  • 正如@OliCharlesworth 所说。构建“指令队列”(我假设您的意思是下一个处理指令的顺序)发生在硬件级别(使用执行引擎等);因此,当由于中断而更改顺序时,对其进行的任何调整也都是由硬件处理的。作为用户,您通常不知道接下来会发生什么,因此很难/不可能参与其中。
  • 中断发生时指令队列失效(所有前瞻执行的指令都回滚)。
  • 本 PDF 的第 6 章可能会对您有所帮助:intel.com/content/www/us/en/architecture-and-technology/…
  • @AlexisWilke 谢谢! :) 我正在经历它

标签: assembly interrupt x86-16 interrupt-handling microprocessors


【解决方案1】:

您不太清楚“指令队列”的含义。

一个含义可能是“预取指令”。在实践中,处理器从最后一个完成指令的点开始推测性地预读指令流,根据各种类型的分支预测算法跟随或不跟随分支。由于这些是读取,因此如果处理器决定放弃当前指令“流”而使用另一个指令(例如,中断例程),它会简单地忽略其预读。

另一个含义可能是“部分执行的指令(在飞行中/在'管道'中)”,这经常发生在超标量 CPU 中。在异步中断的情况下,处理器必须完成那些影响系统可见状态的操作(例如,已提交对寄存器或内存的写入),并且可能会或可能不会完成其他指令,具体取决于特定处理器的设计者。在同步陷阱的情况下,处理器必须完成影响状态的指令,但简单地放弃其余的(OP 的短语是“将队列归零”,其概念正确但措辞错误)。

[应 OP 的要求添加我所做的评论]: 你说 8086 有一个 6 字节的预取“指令管道”(恕我直言)。可能有一个具有该属性的,但这是实现的细节,没有充分的理由相信这是所有 8086 的属性。对于现代 CPU,指令预取的实现方式完全取决于设计人员的聪明才智。几乎所有你可以合理预测的是会有一些预取方案,你很难在你的应用程序中检测到它的存在,除了对性能的影响和关于自修改代码的有趣规则。

[回答OP的第二个问题]: 其次,我们是否需要手动处理 IP(例如,在中断时将其压入堆栈)还是由中断服务例程为我们处理?

对于任何类型的陷阱或中断,存储架构定义的状态(“寄存器”、PC 等)就足够了。对于许多处理器来说,硬件存储架构状态的关键子集就足够了,并让中断例程存储(并最终恢复)其余部分。因此,存储整个状态的责任由硬件和软件分担(以节省硬件的实现工作量)。

对于 x86 系列,通常指令指针 (IP) 和标志寄存器由硬件推送到当前堆栈,控制转移到中断,并且中断例程具有将其余寄存器通常存储在一种操作系统定义的数据结构,通常称为“上下文块”。中断例程完成它的工作,或者通过重新加载寄存器将控制权返回给应用程序,然后使用特殊的 IRET 指令重新加载 IP 和标志,或者将控制权转移到选择运行其他活动的 OS 调度程序,最终使用保存的上下文块内容重新启动应用程序。

一个真正快速的中断例程可能只保存足够的寄存器来完成它的关键工作,然后在返回给被中断者之前恢复这些寄存器。

【讨论】:

  • 不错的答案 :) 是的,instruction queue 是存储来自代码段的pre-fetched instructions 的队列。
【解决方案2】:
  • 发生中断或陷阱时,CPU 通过停止与缓存同步,直到所有挂起的缓存操作完成或被抢占。
  • 如果缓存加载已经在进行中,它会完成,但其他 队列中等待的操作被抢占。
  • 队列存储为缓存内部状态的一部分,因此当上下文恢复时,抢占操作会重新排队。

【讨论】:

  • 哪个文件说明了这一点?我可以在Volume 3A -- System Programming Guide, Part 1 中看到他们谈论了很多关于中断和异常的内容,但没有谈论如何处理缓存。另外,我不记得曾经看到过什么说 CPU 状态会恢复,尽管现在我们可以保存线程之间的状态,我想这可以应用于中断。此外,您的回答在处理器品牌或代际之间没有任何区别......
  • 我从未见过任何处理器设计将任何类似于“指令队列”的东西存储为“缓存内部状态的一部分”。这在技术上可能是可行的,但如果有的话,晶体管或复杂性不值得回报。存储架构定义的状态(“寄存器”、PC 等)就足够了。对于许多处理器来说,存储架构状态的关键子集(例如 PC 和标志)就足够了,并让中断例程存储(并最终恢复)其余部分。
  • en.wikipedia.org/wiki/Prefetch_input_queue#Instruction_queue 8086 架构有一个六字节的预取指令流水线。由于执行单元正在执行当前指令,总线接口单元会提前从内存中读取多达六个字节的操作码。
  • pre-fetch instruction pipeline 和 8086 上的 pre-fetch instruction queue 表示相同的意思——它们缓存指令(通过从 CS 内存段加载它们)通过前瞻到 CS 内存段(异步)以保持执行单元忙 :)
  • 为了澄清我的答案,我区分了“处理器内部状态”(通常有某种指令预取数据)和我认为的“缓存(内部?你的术语)状态”表示 内存 状态的图像,并且通常可以在处理器的控制转移中存活(嗯,持续更新)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-17
  • 2011-02-10
  • 1970-01-01
  • 2018-04-28
  • 1970-01-01
相关资源
最近更新 更多