为什么6502的中断标志的初始状态是1?

8
我正在模拟6502处理器,并且已经接近完成(现在处于测试阶段)。我正在使用来自nesdev网站的一些NES测试,并且它告诉我初始时中断标志和未使用的第五个标志都应该设置为1(即禁用中断),但是为什么? 我可以理解未使用的标志部分,因为它是...嗯...未使用的,但是我不理解中断标志。我尝试在谷歌上搜索,一些网站确认它应该设置为1,但没有人解释原因。为什么程序一开始就要阻止中断呢?
2个回答

14

在上电时,CPU 的内部电路将“未使用”标志位硬连到逻辑“1”。这个标志位只能是“1”,因为它不由任何内部标志或寄存器控制,而是由连接到高信号线的物理连接确定。

状态寄存器中的“I”标志在 CPU 重置逻辑时初始化为“1”,当然也可以通过“SEI”和“CLI”程序指令以及 CPU 本身进行修改(例如在 IRQ 处理过程中)。默认状态为“1”(从而设置中断禁止标志)的原因是,主机系统可以执行启动/复位代码,而无需考虑和安排 IRQ 断言的服务。

许多 6502 主机系统依赖于一些外部触发源来引发 IRQ 和 NMI 断言——通常是一个 VIA 或 CIA 伴侣芯片,由 MOS Technology 特别设计为接口适配器,具有可配置的定时器和其他事件响应器,与 6502 无缝协同工作,根据预定的硬件条件引发中断。这些伴侣芯片本身需要一些程序驱动配置,以便将它们设置为已知状态,开始监视硬件事件并相应地引发中断。

由于这些芯片可能被硬件初始化为潜在的不确定状态,因此6502不想立即开始服务于这些中断,因为这些中断可能完全是虚假的。通过将“I”标志默认设置为“开启”,CPU开始其重置程序执行,知道软件可以初始化主机系统的其余部分 - 包括支持芯片如VIAs和CIAs - 在整个系统处于可以处理它们的状态之前,不存在虚假中断的可能性。举个例子,考虑一个情景,CPU IRQ向量在ROM中指向RAM中的间接向量,RESET代码通过将IRQ服务例程地址初始化到RAM向量来初始化它。如果在RESET代码初始化RAM向量之前发生了IRQ,则它几乎肯定指向随机地址(可能但不保证为$0000),很可能会导致系统崩溃。通过默认设置“I”标志,直到程序发出“CLI”命令,IRQs才不会发生,而这是在RAM向量地址已正确初始化以指向有效的IRQ服务例程后。

如果你研究6502 RESET代码的常见示例,你会看到一系列系统初始化例程的重复主题,用于设置主机环境(包括支持芯片计时器寄存器以进行IRQ生成),然后最后一件事情是运行'CLI'指令。大多数环境往往是基于IRQ驱动,以精确的间隔执行其工作和服务例程(例如每个视频帧执行一次),因此RESET代码以'CLI'结尾来表示初始化 - 包括IRQ生成设置 - 已完成且可以开始IRQ服务。

现在,说了这么多,还有什么可以阻止NMI在RESET处理期间的任何时候被断言呢?CPU会刻苦地暂停RESET程序,并跳转到NMI ROM向量 - 在这种情况下,“I”标志没有影响(正如你所预期的那样 - NMI是不可屏蔽的,不能被忽略)。因此,具有讽刺意味的是,虽然“I”标志默认设置为“1”以保护RESET代码免受虚假或过早的IRQ的干扰,但仍然始终存在虚假NMI的可能性,该问题无法阻止,并且如果向量指向RAM(直接或间接)则可能引起相同的问题。

程序员的任务是找到一种管理这样不及时的 NMIs 的方法,使得如果它们发生了,它们就没有任何影响,或者至少不会干扰 RESET 处理。因此,可以说,如果软件必须考虑这种情况,那么为 IRQ 做同样的事情并不需要更多的努力 - 这意味着在 CPU 初始化电路中默认将 'I' 标志设置为 '1' 可以被取消,或者将 NMIs 硬连线为在 RESET 期间被忽略。但当然,它们在所有情况下都不会是“不可屏蔽的”,你需要一个特殊的“RESET” 标志在状态寄存器中,您可以清除该标志以告诉CPU已完成RESET处理,并且NMIs现在可以正常服务。但是我岔开了话题。


这个回答...哇。非常感谢。这只留下了一个简单的问题。你从哪里获取所有这些信息?大多数6502(和变种)文档,甚至没有足够正确的信息供我模拟系统,更不用说理解其内部工作原理了。 - ZimZim
2
嘿,30多年的辛苦经验往往会导致对一个主题有相当深入的理解 - 我从1982年开始编写6502代码。 :) 除此之外,关于6502的信息很多,但往往分散在多个来源,并且通常特定于芯片的某个方面(例如,关于IRQ处理、BRK指令、未记录的操作码等的讨论)。6502.org是一个明显的起点,因为它是一个长期存在的社区。Visual6502.org是一个相当新的新来者,但具有有用的信息。当然还有我的博客。 ;) - Eight-Bit Guru
据我所知,硬件只是保持复位几毫秒,直到电路稳定下来,以避免上电NMI。 - John Moser
这不是关键点。在保持复位线的情况下,CPU处于非执行状态-因为没有执行指令,所以不会服务于任何中断。但是当复位被释放后,CPU开始其启动处理过程,并且在此阶段可能会从外部电路中接收到NMI信号,因此必须优雅地处理这些信号(或在NMI处理程序中忽略它们)。 - Eight-Bit Guru

4
通常,一台机器需要在接收中断之前设置其全局状态才能安全运行。如果中断最初已启用,则您永远不会知道哪些内容已经初始化,哪些没有在您的中断例程中。
因此,它是允许在事件开始发生之前强制实施已知状态的问题。
在NES上,这可能几乎没有区别-内置硬件生成非可屏蔽中断,并且在被告知开始之前不会这样做。具有标准中断生成硬件的大多数插卡也需要事先告知开始生成中断,而不仅仅是从通电开始执行。
但是,这种6502行为对该部分来说是通用的。他们可能试图避免的一个示例问题可能是启动时间为两秒钟且生成中断的键盘的系统。中断例程可能会缓冲击键。但是,如果它在系统其他方面设置之前尝试这样做,则可能会将字节写入内存中的随机位置。

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