题目
使用Python语言,实现一个MIPS的汇编器,将你常用到的汇编指令翻译为机器指令。
输入:汇编语言程序文件
输出:二进制或十六进制文件,采用Xilinx Vivado的COE文件格式
例如,对类似下面的汇编语言程序,能够顺利翻译为机器指令:
# 这是注释
addi $t1, $0, 100 #这也是注释,空行应该能够顺利跳过
addi $t2, $0, 200
add $t3, $t1, $t2 # #符号后面的是注释
addi $t4, $0, 400
and $t5, $t1, $t4
sub $t2, $t3, $t4
要求支持以下指令
跳转分支类指令:bltz、j、jal、beq、blez
立即数类指令:addi、slti、andi、ori、xori、lui
Load/Store类指令:lb、lh、lw、sb、sh、sw
R类型指令:sll、srl、sra、jr、jalr、add、sub、and、or、xor、nor、slt
伪指令:
nop(空操作,等效于addi $0, $0, 0)
li $x, abcd(将一个32位立即数abcd加载到目标寄存器x,请使用lui等指令序列实现,请注意立即数是补码形式)
mv $a, $b(将寄存器b内容复制到寄存器a中,等效于addi $a, $b, 0)
not $a, $b(将寄存器b内容取反后复制到寄存器a中,等效于xori $a, $b, -1)
neg $a, $b(将寄存器b内容取负后复制到寄存器a中,等效于sub $a, $0, $b)
输出的文件,采用COE文件格式。例如:
; This .COE file specifies the contents for a block memory of depth=16, and width=32.
memory_initialization_radix=16;
memory_initialization_vector=
12345678,
00ABCDEF,
AABBCCDD,
7788EEAA,
45678ABC,
12378221,
901AC912,
0034ABCD,
89898989,
56565656,
99112233,
16161616,
ABC888DD,
ED00ABCD,
78787777,
99090909;
解决方案
# Read and format the file
def justify_over(a, len):
if len > a:
return False
else:
return True
path = "mips.asm"
formatted = []
addr = {
}
k = 0
PC = 0x00000000
PC = int(PC)
cnt = 0
Rtype = ['sll', 'srl', 'sra', 'jr', 'jalr', 'add', 'sub', 'and', 'or', 'xor', 'nor', 'slt', 'sllv', 'srlv', 'srav',
'mult', 'mfhi', 'mflo', 'mthi', 'mtlo']
Itype = ['addi', 'slti', 'andi', 'ori', 'xori', 'lui']
Jtype = ['bltz', 'bgez', 'j', 'jal', 'beq', 'bne', 'blez', 'bgtz']
L_Stype = ['lb', 'lh', 'lw', 'sb', 'sh', 'sw']
Dtype = ['nop', 'li', 'mv', 'not', 'clear']
with open(path, "r", encoding="utf-8") as file:
lines = file.readlines()
for i in range(len(lines)):
formatted.append([])
line = lines[i]
# delete the annotation and empty line
if len(line) == 1:
continue
if '#' in line:
line = line[:line.index('#')]
if len(line) == 0:
continue
# delete the '\n'
if '\n' in line:
line = line[:-1]
# format the mnemonic and operand
mne = line.split()[0]
formatted[i].append(mne)
line = line[len(mne) + 1:]
line = line.lstrip()
if len(line) == 0:
continue
line_list = line.split(',')
for j in range(len(line_list)):
line_list[j] = line_list[j].strip()
formatted[i] += line_list
k = 0
for i in range(len(formatted)):
if len(formatted[i]) == 0:
continue
k += 1
if len(formatted[i]) == 1 and formatted[i][0] not in Rtype and formatted[i][0] not in Itype and formatted[i][
0] not in L_Stype and formatted[i][0] not in Jtype and formatted[i][0] not in Dtype:
addr[(formatted[i][0])[:-1]] = int(PC + 4 * (k - 1)) - len(addr)
register = {
'$0': 0,
'$at': 1,
'$v0': 2,
'$v1': 3,
'$a0': 4,
'$a1': 5,
'$a2': 6,
'$a3': 7,
'$t0': 8,
'$t1': 9,
'$t2': 10,
'$t3': 11,
'$t4': 12,
'$t5': 13,
'$t6': 14,
'$t7': 15,
'$s0': 16,
'$s1': 17,
'$s2': 18,
'$s3': 19,
'$s4': 20,
'$s5': 21,
'$s6': 22,
'$s7': 23,
'$t8': 24,
'$t9': 25,
'$k0': 26,
'$k1': 27,
'$gp': 28,
'$sp': 29,
'$fp': 30,
'$ra': 31
}
codeToWrite = []
k = 0
for i in range(len(formatted)):
if len(formatted[i]) == 0:
continue
try:
# R type:sll、srl、sra、jr、jalr、add、sub、and、or、xor、nor、slt、sllv、srlv、srav、mult、mfhi、mflo、mthi、mtlo
k += 1
if formatted[i][0] in Rtype:
op = '000000'
rs = '00000'
rt = '00000'
rd = '00000'
shamt = '00000'
funct = '000000'
match formatted[i][0]:
case 'sll':
formatted[i][3] = int(formatted[i][3])
if formatted[i][3] >= 32:
print("Error\n line %d: invalid immediate" % (i + 1))
continue
rd = bin(register[formatted[i][1]])[2:].zfill(5)
rt = bin(register[formatted[i][2]])[2:].zfill(5)
shamt = bin(formatted[i][3])[2:].zfill(5)
case 'srl':
formatted[i][3] = int(formatted[i][3])
if formatted[i][3] >= 32:
print("Error\n line %d: invalid immediate" % (i + 1))
continue
funct = '000010'
rd = bin(register[formatted[i][1]])[2:].zfill(5)
rt = bin(register[formatted[i][2]])[2:].zfill(5)
shamt = bin(formatted[i][3])[2:].zfill(5)
case 'sra':
formatted[i][3] = int(formatted[i][3])
if formatted[i][3] >= 32:
print("Error\n line %d: invalid immediate" % (i + 1))
continue
funct = '000011'
rd = bin(register[formatted[i][1]])[2:].zfill(5)
rt = bin(register[formatted[i][2]])[2:].zfill(5)
shamt = bin(formatted[i][3])[2:].zfill(5)
case 'jr':
funct = '001000'
rs = bin(register[formatted[i][1]])[2:].zfill(5)
case 'jalr':
funct = '001001'
rs = bin(register[formatted[i][1]])[2:].zfill(5)
case 'add':
funct = '100000'
rd = bin(register[formatted[i][1]])[2:].zfill(5)
rs = bin(register[formatted[i][2]])[2:].zfill(5)
rt = bin(register[formatted[i][3]])[2:].zfill(5)
case 'sub':
funct = '100010'
rd = bin(register[formatted[i][1]])[2:].zfill(5)
rs = bin(register[formatted[i][2]])[2:].zfill(5)
rt = bin(register[formatted[i][3]])[2:].zfill(5)
case 'and':
funct = '100100'
rd = bin(register[formatted[i][1]])[2:].zfill(5)
rs = bin(register[formatted[i][2]])[2:].zfill(5)
rt = bin(register[formatted[i][3]])[2:].zfill(5)
case 'or':
funct = '100101'
rd = bin(register[formatted[i][1]])[2:].zfill(5)
rs = bin(register[formatted[i][2]])[2:].zfill(5)
rt = bin(register[formatted[i][3]<