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

来源:互联网 发布:php错误日志在哪 编辑:程序博客网 时间:2024/06/05 22:42

这一章的项目是自己编写一个汇编编译器,实现机器码到二进制码的转换。建议大家照着书上的流程和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/pythonimport sysimport Parserimport Codefilename=sys.argv[1]rfile = open(filename,'r')wfile = open('prog.hack','w')#main loopline=rfile.readline()flag=Parser.hasMoreCommands(line)while flag:#clean the line which starts with // or blank lineswhile line == '\n' or line.startswith('//'):line=rfile.readline()ctype=Parser.commandType(line)#compare command typeif 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 partif 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/pythonimport Parserdef 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 destcodedef 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 compcodedef 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/pythondef hasMoreCommands(line):if not line:return 0else:return 1def advance(rfile,line):line=rfile.readline()return linedef 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 lettersreturn symbolflagdef 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')


0 0