指令集仿真器指南

问题描述 投票:4回答:1

我对编写类似Gameboy和其他掌上游戏机的模拟器很感兴趣,但是我读的第一步是模拟指令集。我在这里找到了一个链接,该链接对初学者来说可以模拟Commodore 64 8位微处理器,但事实是我对模拟指令集一无所知。我知道mips指令集,所以我认为我可以设法理解其他指令集,但是问题是模拟它们意味着什么?

注意:如果有人可以向我提供针对初学者的指令集仿真分步指南,我将不胜感激。

注意#2:我打算用C编写。

注3:这是我第一次学习整个仿真过程。

谢谢

编辑:我发现此站点是编写模拟器的详细分步指南,似乎很有希望。我将开始阅读它,希望它对其他正在研究编写模拟器的人也有所帮助。

Emulator 101

emulation instructions microprocessors instruction-set
1个回答
7
投票

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

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

这里是在C语言中的外观的一般概述(不是100%准确):

uint8_t RAM[65536]; //Declare a memory buffer for emulated RAM (64k)
uint16_t A; //Declare Accumulator
uint16_t X; //Declare X register
uint16_t Y; //Declare Y register
uint16_t PC = 0; //Declare Program counter, start executing at address 0
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都具有不同的操作码和存储器寻址方案。您将不得不处理字节序和字节顺序,当然还有指针。如果您还没有的话,我将对C语言中的指针和类型转换有深入的了解。要操作标志寄存器,您必须对C中的按位操作有深入的了解。如果您很聪明,可以使用C宏甚至函数指针来节省一些工作,如上面的CARRY_FLAG示例。

每次执行一条指令时,您都必须使程序计数器增加该指令的大小,这对于每个操作码都是不同的。一些操作码不带任何参数,因此它们的大小仅为1个字节,而其他操作码则采用16位整数,如上面的我的MOV示例所示。所有这些都应该有充分的记录。

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

关于编写指令集仿真器的最难的部分是调试。您如何知道一切是否都能正常进行?有很多资源可以帮助您。人们编写了测试代码,可以帮助您调试每条指令。您可以一次执行一条指令,然后比较参考输出。如果有所不同,则说明您在某处存在错误,可以对其进行修复。

这应该足以让您入门。重要的是,您必须:A)对要模拟的指令集有充分的了解,并且B)对C中的低级数据操作(包括类型转换,指针,按位操作,字节顺序等)有充分的了解。] >

© www.soinside.com 2019 - 2024. All rights reserved.