关于实现简单CPU仿真器的问题

6 c++ binary emulation machine-code

背景信息:最后,我想写一个真机的模拟器,如原版任天堂或Gameboy.但是,我决定我需要在更远,更简单的地方开始.我的计算机科学顾问/教授为我提供了一个非常简单的假想处理器的规范,他先创建了这个处理器.有一个寄存器(累加器)和16个操作码.每条指令由16位组成,前4位包含操作码,其余为操作数.指令以二进制格式给出,例如"0101 0101 0000 1111".

我的问题:在C++中,解析处理指令的最佳方法是什么?请记住我的最终目标.以下是我考虑的一些观点:

  1. 我不能在读取它们时处理和执行指令,因为代码是自修改的:指令可以改变后面的指令.我能看到解决这个问题的唯一方法是存储所有更改,并检查每条指令以检查是否需要应用更改.这可能导致与每条指令的执行进行大量比较,这是不好的.所以,我想我必须以另一种格式重新编译指令.

  2. 虽然我可以将操作码解析为字符串并对其进行处理,但有些情况下整个指令必须作为数字.例如,增量操作码甚至可以修改指令的操作码部分.

  3. 如果我要将指令转换为整数,那么我不确定如何解析int的操作码或操作数部分.即使我将每个指令重新编译为三个部分,整个指令作为int,操作码作为int,操作数作为int,仍然无法解决问题,因为我可能必须递增整个指令然后解析受影响的操作码或操作数.此外,我是否必须编写一个函数来执行此转换,或者是否有一些C++库有一个函数将"二进制格式"的字符串转换为整数(如Java中的Integer.parseInt(str1,2))?

  4. 此外,我希望能够执行诸如移位之类的操作.我不确定如何实现,但这可能会影响我实现这种重新编译的方式.

感谢您提供的任何帮助或建议!

unw*_*ind 5

将原始代码解析为整数数组.这个数组是你计算机的内存.

使用按位运算来提取各个字段.例如,这个:

unsigned int x = 0xfeed;
unsigned int opcode = (x >> 12) & 0xf;
Run Code Online (Sandbox Code Playgroud)

将从0xf存储在a中的16位值中提取最顶端的四位(,此处)unsigned int.然后,您可以使用eg switch()检查操作码并采取适当的操作:

enum { ADD = 0 };

unsigned int execute(int *memory, unsigned int pc)
{
  const unsigned int opcode = (memory[pc++] >> 12) & 0xf;

  switch(opcode)
  {
  case OP_ADD:
    /* Do whatever the ADD instruction's definition mandates. */
    return pc;
  default:
    fprintf(stderr, "** Non-implemented opcode %x found in location %x\n", opcode, pc - 1);
  }
  return pc;
}
Run Code Online (Sandbox Code Playgroud)

修改内存只是写入整数数组的情况,如果需要,也可以使用一些按位数学.