指令集仿真器指南

时间:2012-11-17 17:38:00

标签: emulation instructions microprocessors instruction-set

我有兴趣编写像gameboy和其他掌上游戏机那样的模拟器,但我读到的第一步是模拟指令集。我发现这里有一个链接说初学者模仿Commodore 64 8位微处理器,事情是我不知道有关模拟指令集的事情。我知道mips指令集,所以我认为我可以管理理解其他指令集,但问题是它是什么意思模仿它们?

注意:如果有人可以为我提供初学者指令集仿真的分步指南,我将非常感激。

注意#2:我打算用C语言写作。

注意#3:这是我第一次尝试学习整个仿真事物。

由于

编辑:我发现这个网站是编写模拟器的详细分步指南,看起来很有希望。我将开始阅读它,并希望它也能帮助那些正在研究模拟器的人。

Emulator 101

1 个答案:

答案 0 :(得分:7)

指令集仿真器是一种软件程序,它从软件设备读取二进制数据并执行数据包含的指令,就好像它是访问物理数据的物理微处理器一样。

Commodore 64使用6502微处理器。我为这个处理器写过一次模拟器。您需要做的第一件事是阅读处理器上的数据表并了解其行为。它有什么样的操作码,内存寻址,IO方法怎么样。它的寄存器是什么?它是如何开始执行的?这些都是您在编写模拟器之前需要回答的所有问题。

以下概述了它在C中的表现(不是100%准确):

unsigned uint8_t RAM[65536]; //Declare a memory buffer for emulated RAM (64k)
unsigned uint16_t A; //Declare Accumulator
unsigned uint16_t X; //Declare X register
unsigned uint16_t Y; //Declare Y register
unsigned uint16_t PC = 0; //Declare Program counter, start executing at address 0
unsigned uint16_t FLAGS = 0 //Start with all flags cleared;

//Return 1 if the carry flag is set 0 otherwise, in this example, the 3rd bit is
//the carry flag (not true for actual 6502)
#define CARRY_FLAG(flags)  ((0x4 & flags) >> 2)

#define ADC 0x69
#define LDA 0xA9

while (executing) {
    switch(RAM[PC]) {  //Grab the opcode at the program counter
        case ADC: //Add with carry
            A = X + RAM[PC+1] + CARRY_FLAG(FLAGS);
            UpdateFlags(A);
            PC += ADC_SIZE;
            break;
        case LDA: //Load accumulator
            A = RAM[PC+1]; 
            UpdateFlags(X);
            PC += MOV_SIZE;
            break;
        default:
            //Invalid opcode!

    }
}

根据this reference,ADC实际上在6502处理器中有8个操作码,这意味着您的switch语句中将有8个不同的ADC,每个ADC用于不同的操作码和存储器寻址方案。您将不得不处理endianess和字节顺序,当然还有指针。如果你还没有,我会对C中的指针和类型转换有一个很好的理解。要操作标志寄存器,你必须对C中的按位操作有充分的理解。如果你聪明,你可以使用C宏甚至函数指针来节省一些工作,就像上面的CARRY_FLAG例子一样。

每次执行指令时,必须按程序的大小前进程序计数器,每个操作码的大小不同。有些操作码不带任何参数,所以它们的大小只有1个字节,而其他操作码则采用16位整数,如上面的MOV示例所示。所有这一切都应该有很好的记录。

分支指令(JMP,JE,JNE等)很简单:如果在标志寄存器中设置了某个标志,则将PC加载到指定的地址。这就是如何在微处理器中做出“决定”并模拟它们只是改变PC的问题,就像真正的微处理器一样。

编写指令集仿真器最困难的部分是调试。你怎么知道一切是否正常运作?有很多资源可以帮助您。人们已经编写了测试代码,可以帮助您调试每条指令。您可以一次执行一条指令并比较参考输出。如果有什么不同,你知道你在某个地方有一个bug并且可以修复它。

这应该足以让你入门。重要的是你有A)对你想要模拟的指令集有一个很好的理解和B)对C中低级数据操作的扎实理解,包括类型转换,指针,按位操作,字节顺序等。 / p>