6502 CPU仿真

21

周末到了,所以我会写一个业余项目来放松一下,这样就可以从整个星期的编程中得到解脱。

昨天我编写了MOS 6502 CPU模拟器的框架,实现了寄存器、堆栈、内存和所有操作码。(源代码链接如下)

我可以在我编写的调试器中手动运行一系列操作,但我想加载一个NES rom并将程序计数器指向它的指令,我觉得这是找到有缺陷的操作码最快的方法。

我编写了一个快速的NES rom加载器,并将ROM块加载到CPU内存中。

问题在于我不知道操作码是如何编码的。我知道操作码本身遵循每个操作码一个字节的模式,唯一地标识了操作码,

0 - BRK
1 - ORA (D,X)
2 - COP b

但我不确定在哪里找到操作码参数。它是直接跟在后面的字节吗?在绝对内存中,我想它可能不是一个字节,而是一个short。

有人熟悉这个CPU的内存模型吗?

编辑:我意识到这可能只是一次无望的尝试,但我希望这里有一些老派的苹果和康柏骑士。

编辑:谢谢大家的帮助。在我实现了正确的更改以使CPU可以加载和运行超级马里奥兄弟后,它没有做任何事情,但这是一个好迹象 :)

我上传了源代码:

https://archive.codeplex.com/?p=cpu6502

如果有人曾经想过模拟器是如何工作的,那么它非常容易理解。没有进行最优化处理,但是再说一遍,我正在模拟一个运行速度为2mhz的CPU在一个2.4ghz的机器上 :)


嘿,我现在的情况和你差不多(在发布帖子时)。我想检查一下你的代码,但链接似乎已经失效了。你还有吗? - Petruza
7个回答

13

该操作码占用一个字节,操作数位于接下来的字节中。例如,可以在这里查看字节大小列


那么,我需要修改每个操作码,以便它知道从PC向前查看多远才能获取其参数? - FlySwat
你需要在某个地方保留一个表格,没错。虽然它永远不会超过三个字节。或者直接将其硬编码到执行每个指令工作的代码中。 - moonshadow

4

如果您查看像http://www.atarimax.com/jindroush.atari.org/aopc.html这样的参考文献,您会发现每个操作码都有一个指定的编码:

HEX LEN TIM

HEX是一个1字节的操作码。紧接着它后面是LEN个字节的参数。请参考文献以查看这些参数是什么。TIM数据对于模拟器非常重要——它是执行此指令所需的时钟周期数。您需要这个数据来正确计时。
这些值(LEN、TIM)不是在操作码本身中编码的。您需要将这些数据存储在程序加载器/执行器中。它只是一个大的查找表。或者您可以定义一个迷你语言来编码数据和读取器。

我认为LEN和TIM实际上并没有被编码,我认为你需要提供它们。我已经在时间控制方面做到了这一点,每个操作码都知道它应该花费多少个周期。 - FlySwat
3
实际上在许多情况下确实如此。对于所有带有操作位[4:2]的操作码,该操作码定义了3位编码的寻址模式。我发现这很一致:0=间接寻址X,1=零页寻址,2=立即数寻址(有时是累加器),3=绝对寻址,4=间接寻址Y,5=零页寻址X,6=绝对寻址Y,7=绝对寻址X。 - Mark Renouf

1

这本书可能会有所帮助:http://www.atariarchives.org/mlb/

此外,尝试检查其他任何6502汇编器/模拟器/调试器,以了解如何将汇编语言编码为机器语言。


1
6502手册可以在网络上的各个历史网站上找到。KIM-1随附了这些手册。也许其中包含了你不需要知道的更多信息。

1

0

Apple II的ROM中包含了一个反汇编器,我想那就是它的名字,它会以一种良好的格式显示十六进制操作码、三字符操作码和操作数。

考虑到可用内存非常少,他们设法将操作数字节计数(始终为0、1或2)和整个6502指令集的三字符操作码压缩到一个非常小的空间中,因为实际上并不需要太多空间。

如果你能找到一个Apple II ROM,你可以直接从那里复制粘贴...


0

6502有不同的寻址模式,相同的指令根据其寻址模式有几个不同的操作码。请查看以下链接,了解6502从内存中检索数据或直接从ROM中读取数据的不同方式。

http://obelisk.me.uk/6502/addressing.html#IMM


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