gpt4 book ai didi

c++ - 解码和匹配C/C++中的Chip 8操作码

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:57:38 26 4
gpt4 key购买 nike

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

// Fetch opcode
opcode = memory[pc] << 8 | memory[pc + 1];

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

但是,既然我已经隔离了操作码,那么我真的不知道该怎么做。我正在使用 this操作码表,但我基本上迷失了将读取的十六进制操作码与该表中的操作码标识符进行匹配的方法。另外,我意识到我正在读取的许多操作码中也包含操作数(我假设是后一个字节?),这可能会使我的情况更加复杂。

帮助?!

最佳答案

基本上,一旦有了指令,就需要对其进行解码。例如,从您的操作码表中:

if ((inst&0xF000)==0x1000)
{
write_register(pc,(inst&0x0FFF)<<1);
}

并猜测由于您正在从一条指令访问rom两个字节,因此该地址可能是一个(16位)字地址,而不是字节地址,因此我将其左移了(您需要研究这些指令的编码方式,即您提供的操作码表)不足以做到这一点,而且无需做任何假设)。

还有很多事情要做,我不知道我是否在github示例中写了任何有关它的内容。我建议您创建一个用于在某个地址访存指令的访存功能,一个读存储功能,一个写存储功能,一个读寄存器功能,写寄存器功能。我建议您的解码和执行功能一次只能解码和执行一条指令。正常执行只是在循环中调用它,它提供了执行中断等功能的能力,而无需进行大量额外工作。它还使您的解决方案模块化。通过创建fetch()read_mem_byte()read_mem_word()等函数。您可以对代码进行模块化(以性能为代价),使调试变得更加容易,因为您只有一个地方可以查看寄存器或内存访问并弄清到底是什么还是什么。

根据您的问题以及您在此过程中的位置,我认为编写仿真器之前需要做的第一件事就是编写反汇编程序。由于是固定的指令长度指令集(16位),因此容易得多。您可以从ROM的某个有趣点开始,也可以根据需要从头开始,然后解码所看到的一切。例如:
if ((inst&0xF000)==0x1000)
{
printf("jmp 0x%04X\n",(inst&0x0FFF)<<1);
}

只有35条指令不需花费时间,而是一个下午,也许是整个星期六,这是您第一次解码指令(我根据您的问题认为这是一条指令)。反汇编程序成为仿真器的核心解码器。用仿真代替printf(),甚至更好地离开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或操作系统功能。基本上,这不是您的传统指令集,它带有寄存器以及寻址模式和alu操作的 list 。

关于c++ - 解码和匹配C/C++中的Chip 8操作码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6619882/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com