2013-03-03 55 views
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 
} 

當我執行的指令,我有決定哪些指令的結果將被存儲在(一個寄存器或RAM的字)

switch語句

我希望能夠做到這一點:

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

'bregister'?你的意思是'resultContainer'? – 2013-03-03 07:43:13

+0

很對,謝謝! – 2013-03-03 07:43:57

+0

酷,DCPU/0x10c :) – 2013-03-03 09:11:45

回答

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塊中使用獲取的指針。所以你必須傳遞指針。

+0

之前,我需要能夠訪問''''a'''',這似乎是最好的方式,但它仍然很難看: – 2013-03-10 07:53:56

1

如果我們從另一個考慮問題?執行指令並將結果存儲在一個變量(result)中,然後決定在哪裏放置結果。不起作用?

+0

這是一個好主意,但我不認爲它會工作得很好,因爲大多數指令,如:''''加,b'''',所以我必須把''''了' '''''''''''''''變成一個變量,添加它們,並將結果放入''''a''''中。在計算 – 2013-03-03 07:52:35

0

一個很好的選擇,一個我曾預計的devkit但尚未實施,是生成你的仿真代碼。這是一個久經考驗,久經考驗的解決方案。對於每個操作碼/寄存器組合或一些有效子集,分別生成ADD A,B和SUB X,Y的代碼。您可以使用位掩碼來抓取您正在查找的特定案例,並執行正確的代碼。編譯器應該能夠在引擎蓋下使用跳轉表,並且沒有查找,沒有條件,應該非常高效。