【问题标题】:What exactly is an interrupt?究竟什么是中断?
【发布时间】:2019-08-12 06:04:28
【问题描述】:

我想了解我在 Logisim 中的 6502 类似工作处理器项目的中断到底是什么。 我知道中断会执行以下步骤:

  1. 停止当前程序的处理

  2. 将所有未完成的数据保存到堆栈中

  3. 是否“某事”

  4. 加载回未完成的数据,让程序继续正常运行。

    我的问题是:在 "SOMETHING" 步骤中会发生什么?程序计数器是否被重定向到要执行的特殊程序?比如读取按下按钮的 ASCII 码并将其保存到寄存器或某个内存位置?如果是这样,该特殊程序通常存储在内存中的什么位置?你能制造出能够处理不同类型中断的CPU吗?也许如果你按下按钮“a”那么它的ASCII将存储在A寄存器中,但如果你按下按钮“b”那么它将存储在X寄存器中?

非常感谢任何帮助。

编辑:感谢大家的回答。我学到了很多,现在可以继续我的项目了。

【问题讨论】:

  • 读取和存储(尤其是排队)响应中断的东西是一个很好的通用概念,因为中断本身并不能传达太多信息,甚至可能不是哪个特定的“设备”发出中断信号.此问题中未定义“按钮”和“ASCII 码”。 (PC CPU 从 PC 键盘读取的是“扫描代码”。直到很久很久以后,它才会映射到任何特定字符编码的字符代码。)

标签: hardware interrupt cpu-architecture 6502


【解决方案1】:

我猜你要求硬件中断(IRQ 或 NMI)。在堆栈中的第 2 步(不在堆栈寄存器中)存储了程序计数器和标志寄存器。稍后您调用RTI 以恢复程序执行。程序计数器加载“某物”的起始地址,即中断子程序或处理中断的程序。如果需要修改它们的值并在RTI之前恢复它们,它必须存储A,X,Y寄存器。 IRQ 中断可以用I 标志屏蔽(延迟),并且 NMI 是不可屏蔽的,即它总是被处理。它们有不同的子程序地址。

【讨论】:

  • 我已经将“堆栈寄存器”编辑为“堆栈”,你是对的。我想了解中断期间会发生什么。我的问题得到了回答,中断告诉程序计数器转到不正确的地址 $FFFE,在那里它被重新定位到程序员自己编写的直接地址,并且该地址具有在发生中断时将执行的程序。跨度>
【解决方案2】:

我的问题是:在“某事”步骤中会发生什么?程序计数器是否被重定向到要执行的特殊程序?

6502 可屏蔽中断的情况是这样的:

  • 引发中断(我的意思是芯片上的中断引脚被强制为低电平。
  • 当需要执行一条新指令时,6502 会检查中断引脚是否为低电平以及状态寄存器中的中断屏蔽是否未设置。如果不是这种情况,即如果中断引脚为高电平或中断掩码为高电平,CPU 就会继续执行。
  • 假设需要中断,CPU 将 PC 保存在堆栈中
  • CPU 然后将状态寄存器保存在堆栈中,但 B 位设置为 0。B 位是“中断”位。对于 BRK 指令,它将被设置为 1,这是区分硬件中断和 BRK 指令的唯一方法。
  • 然后 CPU 获取地址 $FFFE$FFFF 并将其填充到 PC 中,因此从该地址重新开始执行。

就是这样。其他一切都取决于程序员,直到程序员执行RTI,然后将状态字和返回地址从堆栈中拉出并恢复到各自的寄存器中。保存所有寄存器和其他数据是程序员的责任。

程序计数器是否被重定向到要执行的特殊程序?比如读取按下按钮的 ASCII 码并将其保存到寄存器或某个内存位置?

没错。在基于 6502 的计算机系统中,内存顶部有三个向量:

$FFFA - $FFFB : 不可屏蔽中断(如上,除了状态寄存器中的I 位被忽略)。

$FFFC - $FFFD : CPU 检测到复位时使用的复位向量

$FFFE - $FFFF:普通中断向量。

以上内容通常在 ROM 中,因为当 CPU 上电时,复位向量(至少)必须存在。每个地址将指向机器操作系统中用于处理中断的例程。

通常,中断程序会首先通过存储在 RAM 中的向量进行间接跳转。这允许在机器运行时更​​改中断程序。

然后中断程序必须确定中断源。例如,在 Commodore PET 上,中断可能源自 VIA 芯片或任何一个 PIA 芯片,并且每个芯片都可能因各种原因引发中断,例如当显示器出现垂直空白时,即当它完成扫描屏幕并返回到顶行时,其中一个 PIA 芯片会引发中断。在此中断期间,PET 执行一个程序来扫描键盘,并执行另一个程序来反转光标。当 VIA 定时器达到零时,可能会发生另一个中断,程序员可以插入一个中断例程,例如切换输出线以生成声音方波。


对cmets中问题的一些回答。

程序计数器转到地址 $FFFE 以重新定位到该地址

不,程序计数器设置为该地址的任何内容。如果你有:

FFFE: 00 
FFFF: 10

程序计数器将设置为$1000(6502 是小端序),这就是中断例程必须开始的地方。此外,NMI 的向量位于$FFFA。正常中断与BRK 指令共享$FFFE,而不是NMI。

复位向量到底是做什么的?它会重置cpu吗?

复位向量包含在处理器通电后或发生复位时运行的代码位置

NMI 和 IRQ 有什么区别?那我也想知道遮罩是怎么回事?是把处理器状态寄存器中的“I”标志设置为高还是低?

6502 状态寄存器包含七个标志。大多数情况下,它们与算术指令的结果有关,例如如果操作的结果为零,则设置 Z,当操作溢出八位并移位时设置 C。 I 标志启用和禁用正常中断 (IRQ)。如果它为零,则将尊重 IRQ 上的中断。如果为 1,则禁用中断。您可以通过SEICLI指令手动设置和禁用它,并在发生中断时自动设置(这是为了防止中断中断中断)。

NMI 是一个不可屏蔽的中断。不同之处在于它忽略了 I 标志的状态并使用了不同的向量。

最后,什么是向量?它们是间接地址的同义词吗?

是的。

哦,如果你知道的话,从 $FFFA 开始的中断地址是如何存储在 ROM 中的,而不是实际 6502 中的 RAM 中?

您必须安排地址解码逻辑将这些地址指向 ROM 而不是 RAM。事实上,在 Commodore 系统中,$F000 的整个块是包含部分操作系统的 ROM。这可能适用于大多数其他基于 6502 的系统。

【讨论】:

  • 感谢您的精彩回答!现在我明白了,当发生中断(IRQ 或 NMI)时,在保存数据后,程序计数器转到地址 $FFFE 以重定位到存储在那里的地址,并且在该重定位地址上将是程序员的程序来写。这太棒了,这就像制作中断的通用方式。
  • 我现在有一个新问题。我不知道有4个中断。我理解 BRK 的目的,但是 1)重置向量到底是做什么的?它会重置cpu吗? 2) NMI 和 IRQ 有什么区别?那我也想知道遮罩是怎么回事?是否将处理器状态寄存器中的“I”标志设置为高或低?最后,什么是向量?它们是间接地址的同义词吗?
  • 哦,如果你知道的话,从 $FFFA 开始的中断地址是如何存储在 ROM 中而不是存储在真实 6502 中的 RAM 中的?
  • @Seijs 地址 $FFFA/B 只是 6502 的观点之一。它可以是 RAM 或 ROM。
  • 这完全是其他级别的东西,也是我访问 SO 的原因。
【解决方案3】:

6502上有四种中断:RESET、NMI、IRQ和BRK。前三个是硬件中断,最后一个是软件中断。硬件中断在微处理器本身的引脚上有物理输入电压。软件中断是由 BRK 指令引起的。

所有中断都是“向量化的”。这意味着当它们发生时,程序计数器 (PC) 会立即从存储在内存中的地址加载,并且指令从该地址继续执行。

地址以两个字节的小端格式存储在 64k 内存空间的末尾。它们是(十六进制):

NMI     $FFFA/$FFFB 
RESET   $FFFC/$FFFD
IRQ     $FFFE/$FFFF 
BRK     $FFFE/$FFFF

对于 NMI、IRQ 和 BRK,在加载中断地址之前,将当前 PC 地址压入堆栈。处理器状态寄存器也被压入堆栈。

将寄存器压入堆栈,足以在中断服务(处理)后恢复执行。然而,A、X 和 Y 寄存器不会自动压入堆栈。相反,中断服务例程应该在必要时执行此操作 - 并在服务结束时将它们从堆栈中拉回。

请注意,IRQ 和 BRK 向量具有相同的地址。为了区分您的服务代码中发生了什么,您需要检查推送的处理器状态寄存器的中断位。如果中断来自 BRK 指令,则设置中断位。

当前执行的指令总是在服务中断之前完成。

中断处理有很多微妙之处。其中之一是在它们同时发生(断言)的情况下哪种类型的中断获胜。另一个是在指令周期中发生中断的点。如果中断发生在指令的倒数第二个周期之前,那么它将在下一条指令上得到服务。如果在倒数第二个周期或之后,则延迟到一个指令之后。

通过使用 SEI 指令在处理器状态寄存器中设置一个位,可以“关闭”或忽略 IRQ 中断。

通常,中断服务程序需要确定中断的原因(磁盘驱动器、键盘等),并确保清除中断条件并执行任何处理(例如,将按键放入缓冲区)。它通常可以通过读/写映射到硬件的特定内存位置来做到这一点。

此链接有更多信息:https://www.pagetable.com/?p=410

更多关于中断如何在真正的 8 位机器中工作的信息(第 59、86、295 页):BBC Microcomputer Advanced User Guide

以及更多关于物理芯片封装的信息,您可以在其中看到芯片封装本身的 NMI、RES(ET) 和 IRQ 引脚(第 2,3 页):6502 Datasheet

【讨论】:

  • 感谢您的回答。部分来自它和@JeremyP 写的那个,我现在明白了中断是如何执行的。我还没有弄清楚 IRQ 和 NMI 之间的区别是什么,我不明白什么是向量。
  • 向量只是从 $FFFA 到 $FFFF 的内存位置。它们是 ROM 还是 RAM 无关紧要,但通常它们是 ROM。将有一个机器代码例程来服务 NMI,例如地址 $ABCD。在这种情况下,$FFFA 处的字节将包含 $CD,$FFFB 处的字节将包含 $AB。发生屏蔽是因为 PSR 中的中断禁用位可以禁用或“屏蔽”IRQ 中断。 NMI 不能被“屏蔽”或禁用,因此不可屏蔽。只有 IRQ 不能被屏蔽 BRK、RESET 或 NMI。
  • 啊哈......所以你的意思是,当 IRQ 被处理时,当它开始执行程序时(例如在 $ABCD),如果其中的程序有 CLI 指令,那么中断在没有完成中断程序的情况下将被禁用,并且基本上将执行RTI?换句话说,CLI 将像 RTI 在 IRQ 触发程序中一样工作,而 NMI 忽略 CLI,仅在处理器命中 RTI 时停止?
  • 仅在中断发生时检查中断禁用位,而不是在之后的任何时间。对 I 位的任何更改都将被忽略,只有 RTI 将从中断服务中返回,没有其他内容。除非在您的中断服务中发生另一个中断,但您通常会尝试通过缩短服务程序或使用 CLI 来避免这种情况。
  • 另一个微妙之处是,BRK 指令实际上会将 PC+1 压入堆栈。换句话说,它被视为一个两字节的指令。BRK 之后的字节可以包含您喜欢的任何内容,但服务例程可以将其视为错误代码或其他类型的状态。
【解决方案4】:

中断是通过硬件或软件向正在运行的处理器发出的信号,以便处理器会注意该动作并根据中断消息执行动作。 中断分为三种:

  • 内部中断:- 包括时钟周期中断,其中 cpu 必须执行特定操作直到特定时间,并且必须去执行另一个操作。
  • 软件中断:- 当软件本身出现问题或错误时,会发生此中断。例如,用户尝试将某物除以零并发生错误。还有中断。
  • 外部中断:- 外部中断由 IO 设备(例如鼠标和键盘)引起。

Cpu 旨在处理此类中断,并在中断发生之前恢复进程。

【讨论】:

  • 我认为您的意思是“定时器中断”,即 CPU 可以编写一个定时器,使其每 10 毫秒或其他时间中断一次。操作系统可能会更新“时钟”变量以跟踪计时器中断处理程序中的时间,并且通常运行调度程序以查看它是否应该进行上下文切换。 (如果这是一个多任务操作系统!)。 “时钟周期”通常是任何东西可以在 CPU 中占用的最短时间,例如现代 CPU 上一条 add 指令的延迟。 (例如,现代 x86 CPU 的时钟可以运行在高达 4 或 5 GHz)。你显然不能这么快处理中断,没有时间做其他事情了。
猜你喜欢
  • 2014-10-28
  • 2012-08-27
  • 2010-11-12
  • 2011-03-18
  • 2011-01-22
  • 1970-01-01
相关资源
最近更新 更多