第七章:虚拟机1:堆栈运算

本文旨在介绍如何构建一个虚拟机翻译器的初始阶段,将VM程序转化为.asm文件。主要内容包括理解VM的算术逻辑指令和堆栈操作如push, pop,并映射到汇编语言,通过操作D,A寄存器和内存实现翻译。" 78356192,7377630,FreeMarker模板语言详解,"['Java Web', '模板引擎', 'Freemarker语法']

目标:构建vm翻译器的第一部分,本质也是文本翻译,将vm程序翻译成.asm文件。


分析:首先熟悉vm程序的指令,本章涉及算数逻辑指令和push,pop指令,需要将其映射为汇编指令,汇编指令则直接操作D,A寄存器和内存。关键是明确这种映射关系。


Vmtranslator.py:

<span style="font-size:12px;">import sys,os
import Parser
import CodeWriter

filename=sys.argv[1]
rfile = open(filename,'r')
wfile = CodeWriter.setFileName(filename)
wfile.write('@256\nD=A\n@SP\nM=D\n')
line=Parser.advance(rfile)
flag=Parser.hasMoreCommands(line)
while flag:
	while line == '\n' or line.startswith('//'):
		line=rfile.readline()
	ctype=Parser.commandType(line)
	if ctype == 'C_ARITHMATIC':
		attribute1=Parser.arg1(line).strip()
		CodeWriter.writeArithmatic(wfile,attribute1)
	elif ctype in ('C_PUSH','C_POP'):
		attribute1=Parser.arg1(line).strip()
		attribute2=Parser.arg2(line).strip()
		CodeWriter.writePushPop(wfile,ctype,attribute1,attribute2)
	line=Parser.advance(rfile)
	flag=Parser.hasMoreCommands(line)

rfile.close()
CodeWriter.Close(wfile)</span>

Parser.py:
<span style="font-size:12px;">Arith=('add','sub','neg','eq','gt','lt','and','or','not')

def hasMoreCommands(line):
	if not line:
		return 0
	else:
		return 1

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

def commandType(line):
	if line.find('push')>=0:
		return 'C_PUSH'
	elif line.find('pop')>=0:
		return 'C_POP'
	elif line.strip() in Arith:
		return 'C_ARITHMATIC'

def arg1(line):
	if commandType(line) is 'C_ARITHMATIC':
		return line.strip()
	else:
		spline=line.split(' ')
		return spline[1]

def arg2(line):
	if commandType(line) in ('C_POP','C_PUSH','C_FUNCTION','C_CALL'):
		spline=line.split(' ')
		return spline[2]</span>

CodeWriter.py:

<span style="font-size:12px;">import sys,os
import Parser
CODEFLAG1=0
CODEFLAG2=0

def setFileName(filename):
	filetuple=os.path.splitext(filename)
	wfile = open(filetuple[0]+'.asm','w')
	return wfile

def writeArithmatic(wfile,command):
	global CODEFLAG1,CODEFLAG2
	if command == 'add':
		wfile.write('@SP\nM=M-1\nA=M\nD=M\n@SP\nM=M-1\nA=M\nM=D+M\n@SP\nM=M+1\n')
	elif command == 'sub':
		wfile.write('@SP\nM=M-1\nA=M\nD=M\n@SP\nM=M-1\nA=M\nM=M-D\n@SP\nM=M+1\n')
	elif command == 'neg':
		wfile.write('@SP\nM=M-1\nA=M\nM=-M\n@SP\nM=M+1\n')
	elif command == 'and':
		wfile.write('@SP\nM=M-1\nA=M\nD=M\n@SP\nM=M-1\nA=M\nM=D&M\n@SP\nM=M+1\n')
	elif command == 'or':
		wfile.write('@SP\nM=M-1\nA=M\nD=M\n@SP\nM=M-1\nA=M\nM=D|M\n@SP\nM=M+1\n')
	elif command == 'not':
		wfile.write('@SP\nM=M-1\nA=M\nM=!M\n@SP\nM=M+1\n')
	elif command == 'eq':
		wfile.write('@SP\nM=M-1\nA=M\nD=M\n@SP\nM=M-1\nA=M\nD=D-M\n@RET_TRUE'+str(CODEFLAG1)+'\
			\nD;JEQ\nD=0\n@CONTINUE'+str(CODEFLAG2)+'\n0;JMP\n(RET_TRUE'+str(CODEFLAG1)+')\nD=-1\
			\n(CONTINUE'+str(CODEFLAG2)+')\n@SP\nA=M\nM=D\n@SP\nM=M+1\n')
		CODEFLAG1+=1
		CODEFLAG2+=1
	elif command == 'gt':
		wfile.write('@SP\nM=M-1\nA=M\nD=M\n@SP\nM=M-1\nA=M\nD=M-D\n@RET_TRUE'+str(CODEFLAG1)+'\
			\nD;JGT\nD=0\n@CONTINUE'+str(CODEFLAG2)+'\n0;JMP\n(RET_TRUE'+str(CODEFLAG1)+')\nD=-1\
			\n(CONTINUE'+str(CODEFLAG2)+')\n@SP\nA=M\nM=D\n@SP\nM=M+1\n')
		CODEFLAG1+=1
		CODEFLAG2+=1
	elif command == 'lt':
		wfile.write('@SP\nM=M-1\nA=M\nD=M\n@SP\nM=M-1\nA=M\nD=M-D\n@RET_TRUE'+str(CODEFLAG1)+'\
			\nD;JLT\nD=0\n@CONTINUE'+str(CODEFLAG2)+'\n0;JMP\n(RET_TRUE'+str(CODEFLAG1)+')\nD=-1\
			\n(CONTINUE'+str(CODEFLAG2)+')\n@SP\nA=M\nM=D\n@SP\nM=M+1\n')
		CODEFLAG1+=1
		CODEFLAG2+=1


def writePushPop(wfile,command,segment,index):
	if command == 'C_PUSH':
		if segment == 'constant':
			wfile.write('@'+index+'\nD=A\n@SP\nA=M\nM=D\n@SP\nM=M+1\n')
		elif segment == 'local':
			wfile.write('@LCL\nD=M\n@'+index+'\nA=A+D\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n')
		elif segment == 'argument':
			wfile.write('@ARG\nD=M\n@'+index+'\nA=A+D\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n')
		elif segment == 'this':
			wfile.write('@THIS\nD=M\n@'+index+'\nA=A+D\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n')
		elif segment == 'that':
			wfile.write('@THAT\nD=M\n@'+index+'\nA=A+D\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n')
		elif segment == 'pointer':
			if index == '0':
				wfile.write('@3\n')
			elif index == '1':
				wfile.write('@4\n')
			wfile.write('D=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n')
		elif segment == 'static':
			wfile.write('@'+index+'\nD=A\n@16\nD=A+D\nA=D\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n')
	elif command =='C_POP': 
		if segment == 'local':
			wfile.write('@SP\nM=M-1\nA=M\nD=M\n@LCL\nA=M\n')
			for i in range (0,int(index)):
				wfile.write('A=A+1\n')
			wfile.write('M=D\n')
		if segment =='argument':
			wfile.write('@SP\nM=M-1\nA=M\nD=M\n@ARG\nA=M\n')
			for i in range (0,int(index)):
				wfile.write('A=A+1\n')
			wfile.write('M=D\n')
		if segment == 'this':
			wfile.write('@SP\nM=M-1\nA=M\nD=M\n@THIS\nA=M\n')
			for i in range (0,int(index)):
				wfile.write('A=A+1\n')
			wfile.write('M=D\n')
		if segment == 'that':
			wfile.write('@SP\nM=M-1\nA=M\nD=M\n@THAT\nA=M\n')
			for i in range (0,int(index)):
				wfile.write('A=A+1\n')
			wfile.write('M=D\n')
		if segment == 'pointer':
			wfile.write('@SP\nM=M-1\nA=M\nD=M\n')
			if index == '0':
				wfile.write('@3\n')
			else:
				wfile.write('@4\n')
			wfile.write('M=D\n')
		if segment == 'static':
			wfile.write('@SP\nM=M-1\nA=M\nD=M\n@16\n')
			for i in range (0,int(index)):
				wfile.write('A=A+1\n')
			wfile.write('M=D\n')

def Close(wfile):
	wfile.close()</span>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值