摘要:今天折腾一上午,终于完成了上这个课程的最后一个汇编器项目。这套课程真是没白跟,收获良多,现在已经等不及想看下一期的软件部分了,哈哈。
今天折腾一上午,终于 完成了 Coursera 上 From Nand to Tetris / Part I 这个课程的最后一个汇编器项目。这套课程真是没白跟,收获良多,现在已经等不及想看下一期的软件部分了,哈哈。
下面是我的 python 实现,存个档,同时给同样在看这课程的同学们参考。
注释风格看起来可能有点奇怪,拍脑袋想的,没多少 python 编码经验,还望包涵,稍微解释一下:
#-----------------# # 大块代码用途描述 # #-----------------# ## 分级注释 ### 分级注释 #### 分级注释
import sys import os.path #--------# # tables # #--------# ## symbol table SYMB_TABLE = { "SP": 0, "LCL": 1, "ARG": 2, "THIS": 3, "THAT": 4, "R0": 0, "R1": 1, "R2": 2, "R3": 3, "R4": 4, "R5": 5, "R6": 6, "R7": 7, "R8": 8, "R9": 9, "R10": 10, "R11": 11, "R12": 12, "R13": 13, "R14": 14, "R15": 15, "SCREEN": 16384, "KBD": 24576 } ## comp table COMP_TABLE = { "0": "0101010", "1": "0111111", "-1": "0111010", "D": "0001100", "A": "0110000", "!D": "0001101", "!A": "0110001", "-D": "0001111", "-A": "0110011", "D+1": "0011111", "A+1": "0110111", "D-1": "0001110", "A-1": "0110010", "D+A": "0000010", "D-A": "0010011", "A-D": "0000111", "D&A": "0000000", "D|A": "0010101", "M": "1110000", "!M": "1110001", "-M": "1110011", "M+1": "1110111", "M-1": "1110010", "D+M": "1000010", "D-M": "1010011", "M-D": "1000111", "D&M": "1000000", "D|M": "1010101" } ## dest table DEST_TABLE = { "null": "000", "M": "001", "D": "010", "MD": "011", "A": "100", "AM": "101", "AD": "110", "AMD": "111" } ## jump table JUMP_TABLE = { "null": "000", "JGT": "001", "JEQ": "010", "JGE": "011", "JLT": "100", "JNE": "101", "JLE": "110", "JMP": "111" } #------------------# # helper functions # #------------------# ## determine is Int def isInt(str): try: int(str) return True except ValueError: return False ## determine instruction type def getInsType(ins): if ins[0] == "@": return "a" return "c" ## split instruction ### instruction A ram_variable_num = 16 def valueOfAIns(ins): global ram_variable_num if SYMB_TABLE.has_key(ins[1:]): ins = SYMB_TABLE[ins[1:]] elif isInt(ins[1:]): ins = ins[1:] else: SYMB_TABLE[ins[1:]] = ram_variable_num ram_variable_num += 1 ins = SYMB_TABLE[ins[1:]] bin_value = bin(int(ins))[2:] zero_count = 16 - len(bin_value) zero_str = "0" * zero_count return zero_str + bin_value ### instruction C def splitCIns(ins): c_parts = {} dest_splited = ins.split("=") if len(dest_splited) == 1: c_parts["dest"] = "null" jump_splited = dest_splited[0].split(";") else: c_parts["dest"] = dest_splited[0] jump_splited = dest_splited[1].split(";") if len(jump_splited) == 1: c_parts["jump"] = "null" else: c_parts["jump"] = jump_splited[1] c_parts["comp"] = jump_splited[0] return c_parts #------------# # main logic # #------------# ## first pass ### source file sf_name = sys.argv[1] sf = open(sf_name, "r") ### destination file df_name = os.path.splitext(sf_name)[0] + ".tmp" df = open(df_name, "w") line_num = 0 for ins in sf: # comment ins = ins.split("//")[0] # white space ins = ins.strip() if len(ins) == 0: continue # label if ins[0] == "(" and ins[-1] == ")": SYMB_TABLE[ins[1:-1]] = line_num continue df.write(ins + " ") line_num += 1 sf.close() df.close() ## second pass ### source file sf_name = os.path.splitext(sf_name)[0] + ".tmp" sf = open(sf_name, "r") ### destination file df_name = os.path.splitext(sf_name)[0] + ".hack" df = open(df_name, "w") for ins in sf: ins = ins.strip() ins_type = getInsType(ins) if ins_type == "a": val = valueOfAIns(ins) + " " df.write(val) elif ins_type == "c": parts = splitCIns(ins) val = "111" + COMP_TABLE[parts["comp"]] + DEST_TABLE[parts["dest"]] + JUMP_TABLE[parts["jump"]] + " " df.write(val) sf.close() df.close()
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/45370.html
摘要:第章虚拟机项目实现为防闲逛至此的看官不知所云是一个在线课程,目标是指导学生从逻辑门开始从头到尾完成一整套计算机系统。好像撸串一样的爽快芯片硬件编译原理操作系统应用程序这里提供的是第八章的作业,以供半路摔进坑里的同学们扶一下。。。 [From Nand to Tetris] 第8章 虚拟机项目 python 实现 为防闲逛至此的看官不知所云: From Nand to Tetris 是一...
摘要:从全局来看,大多数计算机只是传递一堆布尔值,所以任何对布尔值友好的语言都可以完成这项工作。将模式应用于这些布尔值能够帮助程序员获得其含义,任何人都要做的最大决策是确定系统将使用哪种字节顺序,并确保所有组件都以正确的顺序在总线之间传递信息。芯片的设计到底有多难?想要回答这个问题最好还是先自己实践一下。最近,来自 BBC 的一名资深软件工程师 Daniel Harper 使用 Go 语言成功模拟...
摘要:从全局来看,大多数计算机只是传递一堆布尔值,所以任何对布尔值友好的语言都可以完成这项工作。将模式应用于这些布尔值能够帮助程序员获得其含义,任何人都要做的最大决策是确定系统将使用哪种字节顺序,并确保所有组件都以正确的顺序在总线之间传递信息。芯片的设计到底有多难?想要回答这个问题最好还是先自己实践一下。最近,来自 BBC 的一名资深软件工程师 Daniel Harper 使用 Go 语言成功模拟...
摘要:作用是将标准输入中的所有大写字母转换为响应的小写字母。的移植过的源代码是在源代码目录下编译的,所以源代码目录等于目标文件目录,所以条件不满足,将执行分支的代码。 一个嵌入式产品的开发阶段,需要不断地把bootloader下载到存储器中,如果存储器使用nand flash,但是...
阅读 1422·2021-11-22 13:54
阅读 4135·2021-09-22 15:56
阅读 1779·2021-09-03 10:30
阅读 1303·2021-09-03 10:30
阅读 2060·2019-08-30 15:55
阅读 1835·2019-08-30 14:13
阅读 2016·2019-08-29 15:19
阅读 2319·2019-08-28 18:13