用C/C++解码和匹配Chip 8操作码

del*_*992 4 c c++ decode emulation opcode

我正在编写一个Chip 8仿真器作为仿真的介绍,我有点迷失.基本上,我已经读过Chip 8 ROM并将其存储在内存中的char数组中.然后,按照指南,我使用以下代码检索当前程序计数器(pc)上的操作码:

// Fetch opcode
opcode = memory[pc] << 8 | memory[pc + 1];
Run Code Online (Sandbox Code Playgroud)

芯片8操作码每个2字节.这是一个指南的代码,我模糊地理解为向内存[pc]添加8个额外的位空间(使用<< 8)然后将内存[pc + 1]与它合并(使用|)并将结果存储在操作码变量中.

既然我已经隔离了操作码,我真的不知道如何处理它.我正在使用这个操作码表,我基本上在将我读取的十六进制操作码与该表中的操作码标识符相匹配方面丢失了.另外,我意识到我正在阅读的许多操作码也包含操作数(我假设后一个字节?),这可能使我的情况更加复杂.

救命?!

old*_*mer 9

基本上,一旦你有了指令,你需要解码它.例如,从您的操作码表:

if ((inst&0xF000)==0x1000)
{
  write_register(pc,(inst&0x0FFF)<<1);
}
Run Code Online (Sandbox Code Playgroud)

并猜测,因为你每个指令访问rom两个字节,地址可能是一个(16位)字地址而不是字节地址所以我把它左移一个(你需要研究这些指令是如何编码的,你提供的操作码表不足以做到这一点,而不必做出假设).

还有很多事情要发生,我不知道我是否在我的github样本中写了一些关于它的内容.我建议你创建一个获取函数,用于获取地址指令,读存储器功能,写存储器功能,读寄存器功能,写寄存器功能.我建议你的解码和执行函数解码,一次只执行一条指令.正常执行只是在循环中调用它,它提供了执行中断和类似事情的能力而无需额外的工作.它还模块化您的解决方案.通过创建fetch()read_mem_byte()read_mem_word()等函数.您模块化您的代码(性能略有降低),使调试变得更加容易,因为您只有一个地方可以查看寄存器或内存访问并找出正在发生的事情.

根据您的问题以及您在此过程中的位置,我认为在编写模拟器之前您需要做的第一件事就是编写反汇编程序.作为一个固定的指令长度指令集(16位),使它更容易.您可以从rom中的某个有趣点开始,或者如果您愿意,可以从头开始,并解码您看到的所有内容.例如:

if ((inst&0xF000)==0x1000)
{
  printf("jmp 0x%04X\n",(inst&0x0FFF)<<1);
}
Run Code Online (Sandbox Code Playgroud)

只有35个指令不应该采取但是一个下午,也许整个星期六,是你第一次解码指令(我假设根据你的问题).反汇编程序成为模拟器的核心解码器.用模拟替换printf(),甚至更好地保留printfs并只添加代码来模拟指令执行,这样你就可以按照执行的方式执行.(同一个交易有一个反汇编单个指令函数,为每个指令调用它,这成为你的模拟器的基础).

您的理解需要更加模糊,因为获取代码行正在做什么,为了完成这项任务,您将必须对位操作有一个强烈的理解.

此外,我会将您提供的代码行称为错误或至少有风险.如果memory []是一个字节数组,编译器可能会很好地使用字节大小的数学运算执行左移,导致零,然后零orred,第二个字节只导致第二个字节.

基本上,编译器有权将其转为:

opcode = memory[pc] << 8) | memory[pc + 1];
Run Code Online (Sandbox Code Playgroud)

进入:

opcode = memory[pc + 1];
Run Code Online (Sandbox Code Playgroud)

这根本不适合你,一个非常快速的解决方案:

opcode = memory[pc + 0];
opcode <<= 8;
opcode |= memory[pc + 1];
Run Code Online (Sandbox Code Playgroud)

会省你一些头疼的事.最小化优化将使编译器不会将中间结果存储到每个操作的ram,从而产生相同(所需)的输出/性能.

我上面写的和上面提到的指令集模拟器并不是为了提高性能,而是为了可读性,可见性和希望教育.我会从类似的东西开始然后如果感兴趣的性能你将不得不重新写它.这个chip8仿真器,一旦经历过,将是一个从零开始的下午任务,所以一旦你完成这个,你第一次可以重写它可能在一个周末三四次,而不是一个巨大的任务(必须重写) ).(缩略图一个人花了我一个周末,大部分时间.Msp430可能更像是一个晚上或两个人的工作.一次又一次地获得溢出标志是最大的任务,后来出现了).无论如何,重点是,看看像mame源这样的东西,大多数(如果不是全部)这些指令集模拟器都是为执行速度而设计的,许多在没有大量研究的情况下几乎无法读取.通常是大量的桌面驱动,有时很多C编程技巧等等.从可管理的东西开始,让它正常运行,然后担心提高它的速度或大小或可移植性等等.这个chip8的东西看起来是基于图形的,所以你还必须在位图/屏幕/任何地方处理大量的线条绘制和其他位操作.或者你可以只调用api或操作系统函数.基本上这个chip8的东西不是你的传统指令集,有寄存器和寻址模式和alu操作的清单.