数据转移指令完成
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