我正在尝试用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(){ }
以及其他我不知道的事情来实现这一目标?
答案 0 :(得分:1)
如果我们从另一个视角看问题怎么办?执行指令并将结果存储在变量(result
)中,然后决定应该将结果放在何处。不行吗?
答案 1 :(得分: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
块中获取的指针。所以你必须传递指针。
答案 2 :(得分:0)
一个很好的选择,我曾计划用于DevKit但尚未实现,是生成您的仿真代码。这是一个历史悠久,久经考验的解决方案。对于每个操作码/寄存器组合或某个有效子集,分别为ADD A,B和SUB X,Y生成代码。您可以使用位掩码来获取您正在寻找的特定情况,并只需执行正确的代码。编译器应该能够在引擎盖下使用跳转表,并且没有查找,没有条件,应该非常有效。