计算机系统要素:第六章 Part1 汇编编译器(nonsymbol)

这一章的项目是自己编写一个汇编编译器,实现机器码到二进制码的转换。建议大家照着书上的流程和API做,先写出nonsymbol的编译器,再写symbol编译器,原因是带symbol的转化规则刚接触时不太容易理解。我使用的语言是python,同时也建议大家使用python这类脚本语言,总共代码不超过150行,非常简洁。

 

首先给不熟悉python模块的同学们写几个TIPS:

1,首先要建立PYTHONPATH,以便于通过cmd命令行导入模块;在cmd窗口中进入文件夹后,输入assembler.pyfilename.asm,filename.asm代表参数,在模块文件中用sys.argv[1]来表示。

2,默认的输出文件为prog.hack,需要在文件夹下建立该文件

3,主要使用了字符串的分割、连接、过滤、进制转化,相关内容google或百度非常方便。


assembler.py

#!/usr/bin/python
import sys
import Parser
import Code

filename=sys.argv[1]
rfile = open(filename,'r')
wfile = open('prog.hack','w')

#main loop
line=rfile.readline()
flag=Parser.hasMoreCommands(line)
while flag:
	#clean the line which starts with // or blank lines
	while line == '\n' or line.startswith('//'):
		line=rfile.readline()

	ctype=Parser.commandType(line)
	#compare command type
	if ctype is 'A_COMMAND':
		AS=Parser.symbol(line)
		AS1=bin(int(AS))[2:]
		AString=AS1.zfill(15)  
		wfile.write('0'+AString+'\n')

	elif ctype is 'L_COMMAND':
		LString=Parser.symbol(line)
		wfile.write('0'+LString+'\n') 
		#L_COMMAND has no meaning in this part

	if ctype is 'C_COMMAND':
		DestString=Code.dest(line)
		CompString=Code.comp(line)
		JumpString=Code.jump(line)
		wfile.write('111'+CompString+DestString+JumpString+'\n')

	line=Parser.advance(rfile,line)
	flag=Parser.hasMoreCommands(line)

rfile.close()
wfile.close()

Code.py

#!/usr/bin/python
import Parser

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

def comp(line):
	compdict={'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'}
	compcode=compdict[Parser.comp(line)]
	return compcode

def jump(line):
	jumpdict={'null':'000','JGT':'001','JEQ':'010','JGE':'011','JLT':'100','JNE':'101',\
	'JLE':'110','JMP':'111'}
	jumpcode=jumpdict[Parser.jump(line)]
	return jumpcode

Parser.py

#!/usr/bin/python
def hasMoreCommands(line):
	if not line:
		return 0
	else:
		return 1

def advance(rfile,line):
	line=rfile.readline()
	return line

def commandType(line):
	if line.find('@')>=0:
		return 'A_COMMAND'
	elif line.find('=')>=0 or line.find(';')>=0:
		return 'C_COMMAND'
	elif line.find('(')>=0:
		return 'L_COMMAND'

def symbol(line):
	symbolflag=line.strip(' @()\n') 
	#be careful about striping needless letters
	return symbolflag

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

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

def jump(line):
	if line.find('=')>=0:
		return 'null'
	elif line.find(';')>=0:
		jumplist=line.split(';')
		return jumplist[1].strip(' \n')
相关文章
相关标签/搜索
每日一句
    每一个你不满意的现在,都有一个你没有努力的曾经。
公众号推荐
   一个历史类的公众号,欢迎关注
一两拨千金