今天早上早些时候,在我的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 = []
新闻热点
疑难解答