今天早上早些時候,在我的Planet Python源中,我讀到了一篇有趣的文章"開發CARDIAC:紙板計算機(Developing upwards: CARDIAC: The Cardboard Computer)",它是關于名為Cardiac的紙板計算機的.我的一些追隨者和讀者應該知道,我有一個名為簡單CPU(simple-cpu)的項目,過去的數月我一直工作于此,并且已經發布了源代碼.我真的應該給這個項目提供一個合適的許可證,這樣,其他人可能更感興趣,并在他們自己的項目中使用.不管怎樣,但愿在這發布之后,我可以完成這件事.
在讀完了這篇文章以及它鏈接的頁面后,我受到了一些啟發,決定為它編寫我自己的模擬器,因為我有編寫字節碼引擎的經驗.我計劃著跟隨這篇文章繼續往前,先寫一篇關于匯編器的文章,接下來是關于編譯器的文章.這樣,通過這些文章,你基本上可以學到,如何用Python為Cardiac創建編譯工具集. 在簡單CPU(simple-cpu)項目中,我已經編寫了一個完整的可工作的匯編器.在內置的游戲中,已經有了可工作的編譯器的最初步驟.我也選擇Cardiac作為一個驗證機器是因為它絕對的簡單.不需要復雜的記憶,每個操作碼只接受單一的參數,所以它是絕好的學習工具.此外,所有的數據參數都是相同的,不需要檢測程序是需要一個寄存器,字符串或者還是內存地址.實際上,只有一個寄存器,累加器.因此,讓我們開始吧!我們將基于類來創建,這樣包含范圍.如果你想嘗試的話,你可以簡單通過子類來增加新的操作碼.首先,我們將集中于初始化例程.這個CPU非常簡單,所以我們只需要初始化下面的內容: CPU寄存器, 操作碼, 內存空間, 讀卡器/輸入, 和 打印/tty/輸出.
class Cardiac(object): """ This class is the cardiac "CPU". """ def __init__(self): self.init_cpu() self.reset() self.init_mem() self.init_reader() self.init_output() def reset(self): """ This method resets the CPU's registers to their defaults. """ self.pc = 0 #: Program Counter self.ir = 0 #: Instruction Register self.acc = 0 #: Accumulator self.running = False #: Are we running? def init_cpu(self): """ This fancy method will automatically build a list of our opcodes into a hash. This enables us to build a typical case/select system in Python and also keeps things more DRY. We could have also used the getattr during the process() method before, and wrapped it around a try/except block, but that looks a bit messy. This keeps things clean and simple with a nice one-to-one call-map. """ self.__opcodes = {} classes = [self.__class__] #: This holds all the classes and base classes. while classes: cls = classes.pop() # Pop the classes stack and being if cls.__bases__: # Does this class have any base classes? classes = classes + list(cls.__bases__) for name in dir(cls): # Lets iterate through the names. if name[:7] == 'opcode_': # We only want opcodes here. try: opcode = int(name[7:]) except ValueError: raise NameError('Opcodes must be numeric, invalid opcode: %s' % name[7:]) self.__opcodes.update({opcode:getattr(self, 'opcode_%s' % opcode)}) def init_mem(self): """ This method resets the Cardiac's memory space to all blank strings, as per Cardiac specs. """ self.mem = ['' for i in range(0,100)] self.mem[0] = '001' #: The Cardiac bootstrap operation. def init_reader(self): """ This method initializes the input reader. """ self.reader = [] #: This variable can be accessed after initializing the class to provide input data. def init_output(self): """ This method initializes the output deck/paper/printer/teletype/etc... """ self.output = []
新聞熱點
疑難解答