3

我正在尝试用 C# 编写一个 CPU 模拟器。机器的对象如下所示:

class Machine 
{
    short a,b,c,d; //these are registers.

    short[] ram=new short[0x10000];  //RAM organised as 65536 16-bit words

    public void tick() { ... } //one instruction is processed
}

当我执行一条指令时,我有一个 switch 语句,它决定指令的结果将存储在什么中(寄存器或 RAM 字)

我希望能够做到这一点:

short* resultContainer;

if (destination == register)
{
    switch (resultSymbol) //this is really an opcode, made a char for clarity
    {
       case 'a': resultContainer=&a;
       case 'b': resultContainer=&b;
       //etc
    }
}
else
{
    //must be a place in RAM
    resultContainer = &RAM[location];
}

然后,当我执行指令时,我可以简单地存储结果,如:

*resultContainer = result;

我一直在试图弄清楚如何在不破坏 C# 的情况下做到这一点。

我如何使用以及可能还有其他我不知道的东西来完成unsafe{}这个fixed(){ }

4

3 回答 3

1

这就是我将如何实现它:

class Machine
{
    short a, b, c, d;
    short[] ram = new short[0x10000];

    enum AddressType
    {
        Register,
        DirectMemory,
    }

    // Gives the address for an operand or for the result.
    // `addressType`and `addrCode` are extracted from instruction opcode
    // `regPointers` and `ramPointer` are fixed pointers to registers and RAM.
    private unsafe short* GetAddress(AddressType addressType, short addrCode, short*[] regPointers, short* ramPointer)
    {
        switch (addressType)
        {
            case AddressType.Register:
                return regPointers[addrCode]; //just an example implementation
            case AddressType.DirectMemory:
                return ramPointer + addrCode; //just an example implementation
            default:
                return null;
        }
    }

    public unsafe void tick()
    {
        fixed (short* ap = &a, bp = &b, cp = &c, dp = &d, ramPointer = ram)
        {
            short*[] regPointers = new short*[] { ap, bp, cp, dp };

            short* pOperand1, pOperand2, pResult;
            AddressType operand1AddrType, operand2AddrType, resultAddrType;
            short operand1AddrCode, operand2AddrCode, resultAddrCode;

            // ... decipher the instruction and extract the address types and codes

            pOperand1 = GetAddress(operand1AddrType, operand1AddrCode, regPointers, ramPointer);
            pOperand2 = GetAddress(operand2AddrType, operand2AddrCode, regPointers, ramPointer);
            pResult = GetAddress(resultAddrType, resultAddrCode, regPointers, ramPointer);

            // execute the instruction, using `*pOperand1` and `*pOperand2`, storing the result in `*pResult`.

        }
    }
}

要获取寄存器和 RAM 数组的地址,必须使用fixed语句。此外,您只能在fixed块中使用获取的指针。所以你必须传递指针。

于 2013-03-03T09:07:56.587 回答
1

如果我们从另一个角度看问题呢?执行指令并将结果存储在变量 ( result) 中,然后决定将结果放在哪里。不工作?

于 2013-03-03T07:50:19.430 回答
0

我为 DevKit 计划但尚未实现的一个不错的选择是生成您的仿真代码。这是一个久经考验、久经考验的解决方案。对于每个操作码/寄存器组合,或一些有效的子集,分别为 ADD A、B 和 SUB X、Y 生成代码。您可以使用位掩码来获取您正在寻找的特定情况并简单地执行正确的代码。编译器应该能够在后台使用跳转表,并且没有查找,没有条件,应该非常有效。

于 2013-03-03T09:15:49.867 回答