资讯专栏INFORMATION COLUMN

[Coursera][From Nand to Tetris / Part I] 第六周 汇编器项目

Taste / 479人阅读

摘要:今天折腾一上午,终于完成了上这个课程的最后一个汇编器项目。这套课程真是没白跟,收获良多,现在已经等不及想看下一期的软件部分了,哈哈。

今天折腾一上午,终于 完成了 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] 第8章 虚拟机项目 python 实现 为防闲逛至此的看官不知所云: From Nand to Tetris 是一...

    alphahans 评论0 收藏0
  • 我这个人不懂什么CPU,于是我用代码模拟出了一个

    摘要:从全局来看,大多数计算机只是传递一堆布尔值,所以任何对布尔值友好的语言都可以完成这项工作。将模式应用于这些布尔值能够帮助程序员获得其含义,任何人都要做的最大决策是确定系统将使用哪种字节顺序,并确保所有组件都以正确的顺序在总线之间传递信息。芯片的设计到底有多难?想要回答这个问题最好还是先自己实践一下。最近,来自 BBC 的一名资深软件工程师 Daniel Harper 使用 Go 语言成功模拟...

    番茄西红柿 评论0 收藏0
  • 我这个人不懂什么CPU,于是我用代码模拟出了一个

    摘要:从全局来看,大多数计算机只是传递一堆布尔值,所以任何对布尔值友好的语言都可以完成这项工作。将模式应用于这些布尔值能够帮助程序员获得其含义,任何人都要做的最大决策是确定系统将使用哪种字节顺序,并确保所有组件都以正确的顺序在总线之间传递信息。芯片的设计到底有多难?想要回答这个问题最好还是先自己实践一下。最近,来自 BBC 的一名资深软件工程师 Daniel Harper 使用 Go 语言成功模拟...

    incredible 评论0 收藏0
  • 基于ARM处理的U-BOOT详细移植总结

    摘要:作用是将标准输入中的所有大写字母转换为响应的小写字母。的移植过的源代码是在源代码目录下编译的,所以源代码目录等于目标文件目录,所以条件不满足,将执行分支的代码。         一个嵌入式产品的开发阶段,需要不断地把bootloader下载到存储器中,如果存储器使用nand flash,但是...

    zengdongbao 评论0 收藏0

发表评论

0条评论

Taste

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<