《计算机系统要素》学习笔记:第六章汇编编译器

学习要点:
1.软件的模块化:下层为上层提供服务,code->parser->assembler
2.学习思路:先写出没有符号表的编译器,再写有符号表的编译器
3.汇编编译器只是做文本的转换,选用Python简单便利
3.python相关知识:
1)字典以及相关操作
2)Python字符串操作

str.startswith()//以某字符串开头
str.strip()  // 清除字符
str.find()  //查找字符
str.split()//拆分字符串为list

3)二进制

a= bin(int('12'))[2:]  //可得字符串‘12’对应的二进制字符串
b=a.zfill(12)  //补足12位

注意:
1)代码只是把机器代码打印出来,并没有写入.hack文件
2)标签符号只需要存入符号表中,形如(loop)不需要机器码

代码实现
code.py

def dest(s):
    dest_dict={'null':'000','M':'001','D':'010','MD':'011','A':'100','AM':'101','AD':'110','AMD':'111'}
    return dest_dict[s]

def comp(s):
    comp_dict={'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'}
    return comp_dict[s]

def jump(s):
    jump_dict={'null':'000','JGT':'001','JEQ':'010','JGE':'011','JLT':'100','JNE':'101', 'JLE':'110','JMP':'111'}
    return jump_dict[s]

parser.py

import code
def hasMoreCommands(i,list):  
    if i>=len(list):  
        return 0  
    else:  
        return 1  

def advance(i):   
    return i+1  

def commandType(line):  
    if line.find('@')>=0:  
        return 'A'  
    elif line.find('=')>=0 or line.find(';')>=0:  
        return 'C'  
    elif line.find('(')>=0:  
        return 'L'  

def symbol(line):  
    symbolflag=line.strip(' @()\n\r')     
    return symbolflag  

def dest(line):  
    if line.find('=')>=0:  
        destlist=line.split('=')  
        return code.dest(destlist[0].strip(' '))
    elif line.find(';')>=0:  
        return code.dest('null')  

def comp(line):  
    if line.find('=')>=0:  
        complist1=line.split('=')  
        return code.comp(complist1[1].strip('\n')) 
    elif line.find(';')>=0:  
        complist2=line.split(';')  
        return code.comp(complist2[0].strip(' '))  

def jump(line):  
    if line.find('=')>=0:  
        return code.jump('null')  
    elif line.find(';')>=0:  
        jumplist=line.split(';')  
        return code.jump(jumplist[1].strip(' \n'))

assembler.py

import sys
import parser
import symboltable
filename = sys.argv[1] 
ifile = open(filename,'r')
strfile = ifile.read()
instr=strfile.split('\n')
i=0
l1=['','\r','\n']
instr_str=[]
for x in instr:
    if not x.startswith('//'): 
        if  x not in l1:
            instr_str.append(x.strip('\r'))
address = 16
sym=symboltable.Constructor()
for x in instr_str:
    if x.find('@') >=0 or x.find('(')>=0:
        symbol=parser.symbol(x)
        if not symboltable.contains(symbol,sym) and not symbol.isdigit():
            sym=symboltable.addEntry(symbol,address,sym)
            address=address+1

while parser.hasMoreCommands(i,instr_str):
    c_type=parser.commandType(instr_str[i]) 
    if c_type=='A':
        str1=parser.symbol(instr_str[i])
        if str1.isdigit():
            str1=bin(int(str1))[2:]
            address = str1.zfill(16)
            print address       
        else:
            if  symboltable.contains(str1,sym):
                str2=bin(symboltable.GetAddress(str1,sym))[2:] 
                address1=str2.zfill(16)
                print address1
    if c_type=='C':
        c_str=parser.comp(instr_str[i])
        d_str=parser.dest(instr_str[i])
        j_str=parser.jump(instr_str[i])
        print '111'+c_str+d_str+j_str
    i=i+1

symboltable.py

def Constructor():
    symboldict={'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}  
    return symboldict 

def addEntry(symbol,address,symboldict):
symboldict[symbol]=address
return symboldict

def contains(symbol,symboldict):
return symboldict.has_key(symbol) 

def GetAddress(symbol,symboldict):
return symboldict[symbol]
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值