基本上,一旦您获得了需要对其进行解码的指令。例如,从您的操作码表中:
if ((inst&0xF000)==0x1000)
{
write_register(pc,(inst&0x0FFF)<<1);
}
并且猜测由于您每条指令访问 rom 两个字节,因此地址可能是(16 位)字地址而不是字节地址,所以我将其向左移动了一个(您需要研究这些指令是如何编码的,您提供的操作码表是不够的,不用做假设)。
还有很多事情要做,我不知道我是否在我的 github 示例中写过任何关于它的内容。我建议您创建一个用于在地址处获取指令的 fetch 函数、一个读存储器函数、一个写存储器函数、一个读寄存器函数、一个写寄存器函数。我建议您的解码和执行功能一次只解码和执行一条指令。正常执行只是在循环中调用它,它提供了执行中断和类似操作的能力,而无需大量额外工作。它还模块化您的解决方案。通过创建 fetch() read_mem_byte() read_mem_word() 等函数。您将代码模块化(以轻微的性能成本为代价),使调试变得更加容易,因为您有一个可以观察寄存器或内存访问并确定正在发生或未发生的事情的地方。
根据您的问题以及您在此过程中所处的位置,我认为在编写模拟器之前您需要做的第一件事就是编写反汇编程序。作为一个固定指令长度的指令集(16 位),这使得它更容易。您可以从 rom 中的某个有趣点开始,或者如果您愿意,也可以从头开始,然后解码您看到的所有内容。例如:
if ((inst&0xF000)==0x1000)
{
printf("jmp 0x%04X\n",(inst&0x0FFF)<<1);
}
只有 35 条指令不应该花一个下午,也许是整个星期六,这是您第一次解码指令(我假设这是基于您的问题)。反汇编程序成为您的模拟器的核心解码器。用仿真替换 printf()s,最好保留 printfs,只添加代码来模拟指令执行,这样您就可以跟踪执行。(同样的交易有一个反汇编一个指令函数,为每条指令调用它,这成为你的模拟器的基础)。
您需要对获取代码行的作用非常模糊,为了完成这项任务,您必须对位操作有深刻的理解。
另外,我会称您提供的那行代码有错误或至少有风险。如果 memory[] 是一个字节数组,编译器可能会很好地使用字节大小的数学来执行左移,产生一个零,然后与第二个字节进行零或排列只会产生第二个字节。
基本上,编译器有权改变它:
opcode = memory[pc] << 8) | memory[pc + 1];
进入这个:
opcode = memory[pc + 1];
这根本不适合你,一个非常快速的解决方法:
opcode = memory[pc + 0];
opcode <<= 8;
opcode |= memory[pc + 1];
将为您省去一些头痛。最小优化将使编译器免于为每个操作将中间结果存储到 ram 中,从而产生相同的(所需的)输出/性能。
我在上面编写和提到的指令集模拟器不是为了性能,而是为了可读性、可见性,并希望具有教育意义。我会从类似的东西开始,然后如果对性能感兴趣,你将不得不重新编写它。这个chip8仿真器,一旦体验过,从头开始是一个下午的任务,所以一旦你第一次完成这个,你可以在一个周末重新编写它可能三四次,而不是一个巨大的任务(必须重新编写)。(拇指调节器花了我一个周末,大部分时间。msp430 可能更像是一个晚上或两个晚上的工作。一劳永逸地正确设置溢出标志是最大的任务,后来才出现)。无论如何,重点是,看看诸如mame来源之类的东西,大多数(如果不是全部)这些指令集模拟器都是为提高执行速度而设计的,如果没有大量研究,许多指令集几乎无法阅读。通常是大量的表驱动,有时还有很多 C 编程技巧等。从可管理的东西开始,让它正常运行,然后担心改进它的速度、大小或可移植性等。这个chip8的东西看起来是基于图形的,所以你还必须在位图/屏幕/任何地方处理大量的线条绘制和其他位操作。或者你可以只调用 api 或操作系统函数。基本上这个chip8的东西不是你传统的带有寄存器和寻址模式和alu操作的清单的指令集。有时有很多 C 编程技巧等。从可管理的东西开始,让它正常运行,然后担心改进它的速度或大小或可移植性或其他什么。这个chip8的东西看起来是基于图形的,所以你还必须在位图/屏幕/任何地方处理大量的线条绘制和其他位操作。或者你可以只调用 api 或操作系统函数。基本上这个chip8的东西不是你传统的带有寄存器和寻址模式和alu操作的清单的指令集。有时有很多 C 编程技巧等。从可管理的东西开始,让它正常运行,然后担心改进它的速度或大小或可移植性或其他什么。这个chip8的东西看起来是基于图形的,所以你还必须在位图/屏幕/任何地方处理大量的线条绘制和其他位操作。或者你可以只调用 api 或操作系统函数。基本上这个chip8的东西不是你传统的带有寄存器和寻址模式和alu操作的清单的指令集。这个chip8的东西看起来是基于图形的,所以你还必须在位图/屏幕/任何地方处理大量的线条绘制和其他位操作。或者你可以只调用 api 或操作系统函数。基本上这个chip8的东西不是你传统的带有寄存器和寻址模式和alu操作的清单的指令集。这个chip8的东西看起来是基于图形的,所以你还必须在位图/屏幕/任何地方处理大量的线条绘制和其他位操作。或者你可以只调用 api 或操作系统函数。基本上这个chip8的东西不是你传统的带有寄存器和寻址模式和alu操作的清单的指令集。