解码和在C / C配套芯片8运codeS ++ [英] Decoding and matching Chip 8 opcodes in C/C++

查看:224
本文介绍了解码和在C / C配套芯片8运codeS ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个芯片模拟器8作为介绍仿真和我有点迷失。基本上,我读了芯片8 ROM并将其存储在内存中的一个字符数组。接着,下面的指导,我用下面的code检索当前程序计数器运code(PC):

I'm writing a Chip 8 emulator as an introduction to emulation and I'm kind of lost. Basically, I've read a Chip 8 ROM and stored it in a char array in memory. Then, following a guide, I use the following code to retrieve the opcode at the current program counter (pc):

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

芯片8运codeS均为2个字节。这是一个指南,我隐约明白如添加8额外位空间内存[PC] code(使用&LT;&LT; 8)然后合并内存[PC + 1]它(使用|)和存储导致运code变量中。

Chip 8 opcodes are 2 bytes each. This is code from a guide which I vaguely understand as adding 8 extra bit spaces to memory[pc] (using << 8) and then merging memory[pc + 1] with it (using |) and storing the result in the opcode variable.

现在,我有运code孤立不过,我真的不知道该怎么办。我使用运code表,我M基本丧失的问候相匹配的十六进制运算codeS我读到该表中的运算code标识符。另外,我认识到,许多运$ C $的CS我读还含有操作数(我假设后者字节),而很可能进一步我的情况复杂化。

Now that I have the opcode isolated however, I don't really know what to do with it. I'm using this opcode table and I'm basically lost in regards to matching the hex opcodes I read to the opcode identifiers in that table. Also, I realize that many of the opcodes I'm reading also contain operands (I'm assuming the latter byte?), and that is probably further complicating my situation.

帮助?!

推荐答案

在github.com搜索thumbulator或mspulator。我有几个非常简单的指令集仿真器,可能会或可能不会有帮助。

At github.com search for thumbulator or mspulator. I have a couple of very simple instruction set simulators that may or may not be helpful.

基本上,一旦你有你的指令需要去code吧。例如从运code表:

Basically once you have the instruction you need to decode it. For example from your opcode table:

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

和猜测,因为你正在访问ROM每个指令两个字节,地址可能是(16位)字的地址不是一个字节的地址,所以我转向它左边的一个(你需要学习这些指令是如何连接codeD,您所提供的运算code表是不足的,还有无需进行假设)。

And guessing that since you are accessing rom two bytes per instruction, the address is probably a (16 bit) word address not a byte address so I shifted it left one (you need to study how those instructions are encoded, the opcode table you provided is inadequate for that, well without having to make assumptions).

有很多更加有发生,我不知道如果我在我的github样品中写任何东西。我建议你​​创建一个读取功能在一个地址,读记忆功能,写记忆功能读寄存器功能取指令,写寄存器的功能。我建议你​​去code和执行功能去codeS和执行一次只能有一个指令。正常执行是只是把它在一个循环中,它提供了做中断之类的东西,如果没有大量的额外工作的能力。它也模块化了您的解决方案。通过创建取()read_mem_byte()read_mem_word()等函数。您的模块化code(在性能有轻微的成本),使调试更加容易,你有一个地方,你可以观看寄存器和存储器存取和弄清楚什么是心不是还是怎么回事。

There is a lot more that has to happen and I dont know if I wrote anything about it in my github samples. I recommend you create a fetch function for fetching instructions at an address, a read memory function, a write memory function a read register function, write register function. I recommend your decode and execute function decodes and executes only one instruction at a time. Normal execution is to just call it in a loop, it provides the ability to do interrupts and things like that without a lot of extra work. It also modularizes your solution. By creating the fetch() read_mem_byte() read_mem_word() etc functions. You modularize your code (at a slight cost of performance), makes debugging much easier as you have a single place where you can watch registers or memory accesses and figure out what is or isnt going on.

根据您的问题,你在哪里,在这个过程中,我认为你需要写一个仿真器之前,首先要做的就是写一个反汇编。在于使得它更容易得多的固定指令长度指令集(16位)。你可以开始在ROM中一些有趣的点,或者在一开始,如果你喜欢,去code你看到的一切。例如:

Based on your question, and where you are in this process, I think the first thing you need to do before writing an emulator is to write a disassembler. Being a fixed instruction length instruction set (16 bits) that makes it much much easier. You can start at some interesting point in the rom, or at the beginning if you like, and decode everything you see. For example:

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

由于只有35指示,不应该采取但一个下午,也许整个周六,是你第一次进行解码的指令(我假设的基础上你的问题)。反汇编成为你的模拟器的核心德$ C $铬。更换的printf()s的仿真,甚至更好离开printfs输出,只是增加code效仿指令执行,这样你可以按照执行。 (同样的协议有拆机单指令函数,调用它的每一个指令,它就会成为你的模拟器的基础)。

With only 35 instructions that shouldnt take but an afternoon, maybe a whole saturday, being your first time decoding instructions (I assume that based on your question). The disassembler becomes the core decoder for your emulator. Replace the printf()s with emulation, even better leave the printfs and just add code to emulate the instruction execution, this way you can follow the execution. (same deal have a disassemble a single instruction function, call it for each instruction, this becomes the foundation for your emulator).

您了解需要超过含糊不清,什么取code线是干什么的,以决绝这个任务你将必须有位操作的深入了解。

Your understanding needs to be more than vague as to what that fetch line of code is doing, in order to pull off this task you are going to have to have a strong understanding of bit manipulation.

此外,我会说这行$ C $的c您提供马车或至少有风险的。如果内存[]是一个字节数组,编译器可能会使用字节大小的数学很好地执行左移,导致零,接零orred与仅在第二个字节的第二个字节的结果。

Also I would call that line of code you provided buggy or at least risky. If memory[] is an array of bytes, the compiler might very well perform the left shift using byte sized math, resulting in a zero, then zero orred with the second byte results in only the second byte.

基本上一个编译器内的权利,把这个:

Basically a compiler is within its rights to turn this:

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

进入这个:

opcode = memory[pc + 1];

这对你不会在所有的工作,非常快速修复:

Which wont work for you at all, a very quick fix:

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

会救你有些头疼。最小优化将节省编译器存储中间结果的RAM导致相同的(期望)输出/性能每个操作。

Will save you some headaches. Minimal optimization will save the compiler from storing the intermediate results to ram for each operation resulting in the same (desired) output/performance.

我写了和上面提到的指令集仿真器不用于性能,而是可读性,可视性,并希望教育。我会开始类似的东西,然后例如,如果性能很感兴趣,你将不得不重新写。这chip8模拟器,一旦经验丰富,将从头开始一个下午的任务,所以一旦你通过这个在第一时间拿到,你可以将它也许在周末重新写了三四次,而不是一个艰巨的任务(不得不重新写)。 (该thumbulator人把我一个周末,大头吧。MSP430的一个是可能更像一两个晚上的工作价值。获取溢出标志权,一劳永逸,是最大的任务,后来这来了)。不管怎样,点之中,看东西像MAME源,大多数,如果不是所有的指令集仿真器是专为执行速度,许多人没有相当数量的研究几乎没有可读性。通常严重表驱动,有时大量的C语言编程技巧等开始与管理的东西,得到它正常工作,然后担心改进它的速度或大小或便携或什么的。这chip8东西看起来是基于图形,所以你要还必须处理位图/屏幕/地方上不少白描等位操作的。或者您也可以拨打API或操作系统功能。基本上这chip8东西不是你的传统指令集,寄存器和寻址模式,ALU操作的一箩筐。

The instruction set simulators I wrote and mentioned above are not intended for performance but instead readability, visibility, and hopefully educational. I would start with something like that then if performance for example is of interest you will have to re-write it. This chip8 emulator, once experienced, would be an afternoon task from scratch, so once you get through this the first time you could re-write it maybe three or four times in a weekend, not a monumental task (to have to re-write). (the thumbulator one took me a weekend, for the bulk of it. The msp430 one was probably more like an evening or two worth of work. Getting the overflow flag right, once and for all, was the biggest task, and that came later). Anyway, point being, look at things like the mame sources, most if not all of those instruction set simulators are designed for execution speed, many are barely readable without a fair amount of study. Often heavily table driven, sometimes lots of C programming tricks, etc. Start with something manageable, get it functioning properly, then worry about improving it for speed or size or portability or whatever. This chip8 thing looks to be graphics based so you are going to also have to deal with a lot of line drawing and other bit manipulation on a bitmap/screen/wherever. Or you could just call api or operating system functions. Basically this chip8 thing is not your traditional instruction set with registers and a laundry list of addressing modes and alu operations.

这篇关于解码和在C / C配套芯片8运codeS ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆