NMI和IRQ中断

8
我正在尝试查找有关6502处理器如何处理中断的信息,但我感到非常困惑。我看过一些相关示例,但它们就像普通的子程序。
我有一些使用8086处理器的经验,并且记得有一些代码可以处理不同的中断。
首先,如果有人能够给我解释NMI和IRQ之间的区别,并附上一些代码,我将不胜感激。更进一步地说,如果您能为我提供更多关于处理键盘中断(例如)的信息,我将不胜感激。

NMI(不可屏蔽中断)是一种不能或不应禁用的中断,因为它们会触发非常严重的问题。IRQ是正常的中断,可以启用/禁用,并可用于不同的目的(例如定时器中断)。我对6502不太熟悉,但如果您需要代码示例,我可以提供x86的示例。 - Jesus Ramos
3个回答

12

有两种不同的中断:可屏蔽和不可屏蔽。6502将在每个指令结束前一个周期对其进行采样。

如果NMI线变为活动状态(边沿触发),则在此操作完成后它将执行NMI例程。

否则,如果IRQ线处于活动状态(电平触发)并且中断禁用标志未设置,则在此操作完成后它将执行IRQ例程。

在这两种情况下,它都会读取跳转向量,将当前程序计数器和状态寄存器推送到堆栈中,设置中断禁用位并跳转到向量指示的位置。从内存中来看,这一切需要七个周期。

除了推送状态寄存器外,还存在谁被认为负责增加程序计数器的差异,因此使用RTI从中断处理程序返回,而不是RTS

NMI向量从FFF A/ FFF Bh读取, IRQ从FFE / FFFF h读取。重置向量位于两者之间,您可以远距离查看重置,并将其视为无法返回的某种类型的NMI。

BRK应该模拟IRQ,但做得不太好。

因此,预期的安排是:对于任何应立即服务的内容,使用NMI。对于可以等待一段时间的任何内容,使用IRQ。相当多的微控制器根本不连接NMI,因为这样你总是需要一个可用的处理程序,但这并非普遍。


1
你能给我展示一下6502汇编中irq和nmi的基本示例吗? - quindimildev
最简单的例子看起来像这样:nmi: rti,它实际上什么也不做。并不是很有用,你需要查看使用NMI更新屏幕的NES开发。 - puppydrum64

9

NMI(不可屏蔽中断)和IRQ(中断请求)是CPU封装上的两个独立物理引脚。

当触发中断时,执行跳转到由0xFFFE和0xFFFF指向的内存位置(对于IRQ)。对于大多数处理器,应使用以下方法将寄存器推送到堆栈中:

PHA
PHX
PHY

SEI可以用来禁用IRQ,但不能禁用NMI。 CLI会重新启用它们。

6502.org有很多教程。


这不是相反的吗?“如果未启用保护模式下的虚拟中断,CLI会清除EFLAGS寄存器中的IF标志。其他标志不受影响。清除IF标志会导致处理器忽略可屏蔽的外部中断。” - Cees Timmerman
@Cees,那是一个x86的参考。与问题完全无关。 - prl

2
回答您的问题,NMI和IRQ在6502上的运行方式几乎相同。这是一个七个周期的操作,可以在MOS 6502编程手册第9章找到,该章节涵盖了所有中断类型指令。正如其他人所指出的,NMI代表不可屏蔽中断,而IRQ代表中断请求(因为它可以被屏蔽)。 NMI使用向量地址FFFA-FFFB,而IRQ和BRK都使用FFFE-FFFF。
请注意,虽然JSR指令将PC寄存器存储为指向JSR指令的最后一个字节,但NMI和IRQ操作将下一条要执行的指令的第一个字节存储。这就是为什么RTS和RTI不能互换使用的一部分。
BRK类似于IRQ,但有两个例外。首先,尽管BRK只是一个字节的指令,但在存储之前PC寄存器会向前移动两次,因此返回地址将是BRK后面的第二个字节。其次,在堆栈上存储的P寄存器(状态寄存器)的值的第4位设置为1,而IRQ则清除该位。请注意,该位实际上没有内部连线,因此如果使用PHP,然后PLA读取状态寄存器,则第4位始终设置,因为6502上的数据线默认为高电平。
MOS 6502编程手册非常适合了解6502的操作方式,因为它概述了如何执行每种类型的6502指令和中断。

稍微解释一下6502如何处理中断,NMI和IRQ线是低电平有效的,这也是为什么P寄存器中的I标志必须清除以生成IRQ的原因。内部逻辑使用NOR门来确定是否将确认中断请求。 - G David

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接