#python3脚本,大黄鸭汇编器

#导入库
#import os,re
from os import remove
from re import search,match
#定义指令字典
YDcmd={'NF':'0000','LD':'0001','SV':'0010','IN':'0011','SW':'0100','WR':'0101','CR':'0110',\
'LA':'0111','LO':'1000','AD':'1001','SB':'1010','JW':'1011','JA':'1100','LL':'1101','LR':'1110','TL':'1111'}
#定义寄存器字典
YDreg={'ZE':'0000','DK':'0001','R0':'0010','R1':'0011','R2':'0100','R3':'0101','R4':'0110','R5':'0111',\
'R6':'1000','R7':'1001','R8':'1010','R9':'1011','RA':'1100','RB':'1101','RC':'1110','PC':'1111'}
#定义伪指令
YDwcm={'NOP':'00000000'}

def 检查out文件():
	try:
		f=open('./out.txt')
		f.close()
	except IOError:
		print ("无预处理文件")
	else:
		remove('./out.txt')
		print ("重新生成预处理文件")
	try:
		f=open('./obj.txt')
		f.close()
	except IOError:
		print ("无输出文件")
	else:
		remove('./obj.txt')
		print ("重新生成输出文件")

def 指令预处理():
	总行数=len(data)#得到行数
	行指针=0#清理行多余字符
	while 行指针<总行数:#遍历list
		inistr=data[行指针]#data的对应行存入inistr
		inistr=inistr.replace(' ','')#去除此行所有空格
		inistr=inistr.replace('\t','')#去除此行所有TAB
		inistr=inistr.upper()#所有字母转为大写
		cntstr=0#字符指针
		while cntstr<len(inistr):#遍历整行,去除无效内容
			if inistr[cntstr]=='#' or inistr[cntstr]=='\n' or inistr[cntstr]=='\r':#如果有#或换行
				inistr=inistr[:cntstr]#储存结束符前的数据
				break#结束遍历
			cntstr+=1#无事发生,下一个字符
		语法检查(待检查的行=inistr,待检查行数=行指针)
		data[行指针]=inistr#存回data
		行指针+=1
	行指针=0#清理多余行
	while 行指针<总行数:#遍历list
		if len(data[行指针])==0:
			data.pop(行指针)#删除行
			行指针=行指针-1
			总行数=len(data)#重置行数
		行指针+=1#切换下一行
	行指针=0
	out=open('./out.txt','w+')#创建中间文件,写入经过预处理的指令
	总行数=len(data)
	while 行指针<总行数:
		out.write(data[行指针])#写入
		out.write('\n')#换行
		行指针+=1
	out.close()

def 语法检查(待检查的行,待检查行数):
	if len(待检查的行)>1:
		ckstr=search(r'[^A-Z\d,;]',待检查的行)
		if ckstr:
			print("错误: 第",待检查行数+1,"行存在非法字符")
		else:
			pass
		ckstr=match(r'NF|LD|SV|IN|SW|NOP',待检查的行)#检测开头是否匹配8b指令
		if ckstr:#8b/NOP指令
			ckstr=match(r'((((NF|LD|SV|IN|SW),(ZE|DK|PC|R[0-9|A|B|C]))|NOP);(((NF|LD|SV|IN|SW),(ZE|DK|PC|R[0-9|A|B|C]))|NOP))|NOP'\
			,待检查的行)
			if ckstr:#匹配8b语法
				if(待检查的行[3:5]==待检查的行[9:11] and 待检查的行[0:3]!='NOP'):#检查并行指令寄存器冲突
					print("警告: 第",待检查行数+1,"行存在寄存器冲突")
			else:#不匹配
				print("错误: 第",待检查行数+1,"行指令语法错误")
		else:#16b指令
			ckstr=match(r'WR|CR|LA|LO',待检查的行)#检测是否匹配16b CMD,RG1,RG2语法
			if ckstr:#16b指令CMD,RG1,RG2
				ckstr=match(r'(WR|CR|LA|LO),(ZE|DK|PC|R[0-9|A|B|C]),(ZE|DK|PC|R[0-9|A|B|C])',待检查的行)
				if ckstr:
					pass
				else:
					print("错误: 第",待检查行数+1,"行指令语法错误")
			else:#16b指令CMD,RG,$H
				ckstr=match(r'(AD|SB|JW|JA|LL|LR|TL),(ZE|DK|PC|R[0-9|A|B|C]),\d\d?\d?',待检查的行)
				if ckstr:
					pass
				else:
					print("错误: 第",待检查行数+1,"行指令语法错误")
				立即数=int(待检查的行[6:])#检查立即数溢出
				if 立即数<0 or 立即数>255:
					print("错误: 第",待检查行数+1,"行立即数位宽错误")


def 执行汇编():
	obj=open('./obj.txt','w+')#创建输出文件
	for strdata in data:
		ckstr=search(r'NF|LD|SV|IN|SW|NOP',strdata)#检测是否匹配8b/NOP指令
		if ckstr:#8b/NOP指令
			if match(r'NOP',strdata) and len(strdata) < 4:#只有NOP
				objdata=YDwcm['NOP']+YDwcm['NOP']#一个周期空指令
			else:#CMD,RG;XX
				objdata=YDcmd[strdata[0:2]]+YDreg[strdata[3:5]]#第一个8b指令输入
				if match(r'NOP',strdata[6:]):#CMD,RG;NOP
					objdata=objdata+YDwcm['NOP']
				else:#CMD,RG;CMD,RG
					objdata=objdata+YDcmd[strdata[6:8]]+YDreg[strdata[9:]]
		else:#16b指令
			if match(r'WR|CR|LA|LO',strdata):#16b指令CMD,RG1,RG2
				objdata=YDcmd[strdata[0:2]]+YDreg[strdata[3:5]]+YDreg[strdata[6:8]]+'0000'
			else:#16b指令CMD,RG,$H
				objdata=YDcmd[strdata[0:2]]+YDreg[strdata[3:5]]+"{:b}".format(int(strdata[6:])).zfill(8)
		obj.write(objdata)#写入
		obj.write('\n')#换行
	obj.close()

##################################################
#--------------------main------------------------#
##################################################
检查out文件()#如果已存在out文件,则重新生成
with open('./asm.txt','r+',encoding='UTF-8') as f:#打开test.txt文件
	data=f.readlines()#按行读取,生成list至data
f.closed#关闭文件
指令预处理()#预处理data,去除注释、多余行、空格,写入out.txt
执行汇编()#二进制代码写入obj.txt
print('结束汇编')