数据转移指令完成
parent
950c72b8fd
commit
b3a2852228
@ -0,0 +1,144 @@
|
||||
import os
|
||||
import re
|
||||
import pin
|
||||
import assembly as ASM
|
||||
from controller import get_hex_str, save_hex_str
|
||||
|
||||
# 允许操作的寄存器
|
||||
ALLOW_REGISTER_MAP = {
|
||||
"a": pin.A,
|
||||
"b": pin.B,
|
||||
"c": pin.C,
|
||||
"d": pin.D,
|
||||
}
|
||||
|
||||
OP2_STR_MAP = {
|
||||
"mov": ASM.MOV,
|
||||
}
|
||||
|
||||
OP1_STR_MAP = {
|
||||
}
|
||||
|
||||
OP0_STR_MAP = {
|
||||
"nop": ASM.NOP,
|
||||
"hlt": ASM.HLT,
|
||||
}
|
||||
|
||||
OP2_VALUE_SET = set(OP2_STR_MAP.values())
|
||||
OP1_VALUE_SET = set(OP1_STR_MAP.values())
|
||||
OP0_VALUE_SET = set(OP0_STR_MAP.values())
|
||||
|
||||
|
||||
class Code:
|
||||
def __init__(self, number, source):
|
||||
self.number: int = number # 行号
|
||||
self.source: str = source # 源代码
|
||||
self._op_str = self._src = self._dst = None
|
||||
|
||||
self.prepare_source()
|
||||
|
||||
def __repr__(self):
|
||||
return f"[{self.number}] - op: {self._op_str}, dst: {self._dst}, src: {self._src} - '{self.source}'"
|
||||
|
||||
def prepare_source(self):
|
||||
tup = self.source.split(",")
|
||||
if len(tup) > 2:
|
||||
raise Exception("指令格式错误")
|
||||
|
||||
if len(tup) == 2:
|
||||
self._src = tup[1].strip()
|
||||
|
||||
tup = re.split(r" +", tup[0])
|
||||
|
||||
if len(tup) > 2:
|
||||
raise Exception("指令格式错误")
|
||||
|
||||
if len(tup) == 2:
|
||||
self._dst = tup[1].strip()
|
||||
|
||||
self._op_str = tup[0]
|
||||
|
||||
@property
|
||||
def op(self):
|
||||
# 根据 mov, add 等指令得到对应的操作二进制码
|
||||
if self._op_str in OP2_STR_MAP:
|
||||
op = OP2_STR_MAP[self._op_str]
|
||||
elif self._op_str in OP1_STR_MAP:
|
||||
op = OP1_STR_MAP[self._op_str]
|
||||
else:
|
||||
op = OP0_STR_MAP[self._op_str]
|
||||
return op
|
||||
|
||||
def get_am(self, addr: str):
|
||||
# 得到目的操作数和源操作数, 返回(寻址方式, 地址)
|
||||
if addr is None:
|
||||
return None, None
|
||||
if addr in ALLOW_REGISTER_MAP: # 如果是寄存器寻址, 且必须是允许的寄存器
|
||||
return pin.AM_REG, ALLOW_REGISTER_MAP[addr]
|
||||
if re.match(r"^[0-9]+$", addr): # 如果是立即数
|
||||
return pin.AM_INS, int(addr)
|
||||
if re.match(r"^0[Xx][0-9A-Za-z]+$", addr): # 如果是16进制立即数
|
||||
return pin.AM_INS, int(addr, 16)
|
||||
if re.match(r"^\[[0-9]+\]$", addr): # 如果是立即数
|
||||
return pin.AM_DIR, int(addr[1:-1])
|
||||
if re.match(r"^\[0[Xx][0-9A-Za-z]+\]$", addr): # 如果是16进制立即数
|
||||
return pin.AM_DIR, int(addr[1:-1], 16)
|
||||
if re.match(r"^\[.+\]$", addr): # 如果是 [a]
|
||||
reg = addr[1:-1]
|
||||
if reg in ALLOW_REGISTER_MAP:
|
||||
return pin.AM_RAM, ALLOW_REGISTER_MAP[reg]
|
||||
|
||||
raise Exception(f"操作数 地址错误: {self}")
|
||||
|
||||
def compile_code(self):
|
||||
amd, dst = self.get_am(self._dst) # 目的操作数
|
||||
ams, src = self.get_am(self._src) # 源操作数
|
||||
# print(amd, dst, ams, src)
|
||||
|
||||
if src and (amd, ams) not in ASM.INSTRUCTIONS[2][self.op]:
|
||||
raise Exception(f"操作数 地址错误: {self}")
|
||||
elif src is None and dst and amd not in ASM.INSTRUCTIONS[1][self.op]:
|
||||
raise Exception(f"操作数 地址错误: {self}")
|
||||
elif src is None and dst is None and self.op not in ASM.INSTRUCTIONS[0]:
|
||||
raise Exception(f"操作数 地址错误: {self}")
|
||||
|
||||
if not src and not dst:
|
||||
amd = dst = ams = src = 0
|
||||
|
||||
# 根据op, 构建 ir寄存器
|
||||
if self.op in OP2_VALUE_SET:
|
||||
ir = self.op | amd << 2 | ams
|
||||
elif self.op in OP1_VALUE_SET:
|
||||
ir = self.op | amd
|
||||
else:
|
||||
ir = self.op
|
||||
return ir, dst, src
|
||||
|
||||
|
||||
def compile_program(input_file: str):
|
||||
codes = []
|
||||
with open(input_file, "r") as f:
|
||||
lines = f.readlines()
|
||||
for idx, line in enumerate(lines):
|
||||
source = line.strip().split(";")[0] # 去掉空格和注释
|
||||
if len(source) == 0:
|
||||
continue
|
||||
code = Code(idx + 1, source)
|
||||
codes.append(code)
|
||||
return codes
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
data_width = 8
|
||||
addr_width = 16
|
||||
input_file = "./test_mov.asm"
|
||||
output_file = "test_mov.bin"
|
||||
|
||||
program_bin_data = []
|
||||
for code in compile_program(input_file):
|
||||
values = code.compile_code()
|
||||
for value in values:
|
||||
program_bin_data.append(value)
|
||||
|
||||
print(get_hex_str(program_bin_data, data_width / 4))
|
||||
save_hex_str(get_hex_str(program_bin_data, data_width / 4), 8, "program.bin")
|
@ -0,0 +1,29 @@
|
||||
; 测试的代码
|
||||
;mov a, 0x0f ; 写入0x0f到A寄存器
|
||||
;mov d, a
|
||||
;mov a, [0x05]
|
||||
;mov b, [a]
|
||||
;nop
|
||||
|
||||
|
||||
; mov [0x0], 0xff
|
||||
|
||||
;mov a, 0xff
|
||||
;mov [0x0], a
|
||||
|
||||
|
||||
mov [0x33], 0x99
|
||||
mov a, [0x33]
|
||||
mov [0x2f], a
|
||||
mov a, 0x2f
|
||||
mov [0x0], [a]
|
||||
|
||||
mov a, 0x00
|
||||
mov [a], 0x05 ; 0x00: 0x5
|
||||
mov a, 0x01
|
||||
mov [a], [0x00] ; 0x01: 0x5
|
||||
mov b, 0x02
|
||||
mov d, 0x00
|
||||
mov [b], [d] ; 0x03: 0x5
|
||||
|
||||
hlt
|
Loading…
Reference in New Issue