From c24e2c791f0713bcef50d9c935faccd35c025c6a Mon Sep 17 00:00:00 2001 From: Giulio De Pasquale Date: Thu, 18 May 2017 20:53:28 +0200 Subject: [PATCH] Assembler con label --- assembler/assembler.py | 146 +++++++++++++++++++++++++++++++---------- 1 file changed, 112 insertions(+), 34 deletions(-) diff --git a/assembler/assembler.py b/assembler/assembler.py index b84aaac..8e1a84f 100644 --- a/assembler/assembler.py +++ b/assembler/assembler.py @@ -47,6 +47,7 @@ class InvalidValue(AssemblerException): def __init__(self, instruction): super().__init__("Invalid value while assembling: {}".format(instruction)) + class VMAssembler: def __init__(self, key): @@ -58,7 +59,6 @@ class VMAssembler: action(instruction) def process_code_line(self, line): - sys.stdout.write("CODE: ") components = [x for x in re.split('\W', line) if x] instruction = VMInstruction(components[0], components[1:]) sys.stdout.write(str(instruction) + "\n") @@ -166,6 +166,21 @@ class VMAssembler: self.assembled_code += opcode.uint8() + imm.uint16() return + def jump(self, instruction): + imm_op_re = re.compile(".*[iI]$") + reg_op_re = re.compile(".*[rR]$") + arg = instruction.args[0] + section = next((x for x in sections if x.name == arg.name), None) + # TODO this is due the VMComponent structure + instruction.args[0].name = section.offset + instruction.args[0].value = section.offset + if imm_op_re.match(instruction.opcode.name): + self.immonly(instruction) + elif reg_op_re.match(instruction.opcode.name): + self.regonly(instruction) + else: + raise AssemblerException() + def single(self, instruction): """ Instruction with no arguments @@ -242,7 +257,7 @@ class VMComponent: return True def isimm(self): - if self.name != self.value: + if not immediate_re.match(str(self.name)): return False return True @@ -256,23 +271,59 @@ class VMInstruction: """ def __init__(self, opcode, instr_list): - immediate_regexp = re.compile("^(0x*|[0-9]*$)") + self.opcode = None + self.args = None + self.size = 1 + self.opcode = next((x for x in ops if x.name == opcode), None) if self.opcode == None: raise InvalidOperation(opcode) self.args = [] for el in instr_list: - if not immediate_regexp.match(el): + if immediate_re.match(el): + # directly append the immediate + self.args.append(VMComponent(el, el)) + self.size += 2 + continue + elif register_re.match(el): # create a VM component for a register reg_comp = next((x for x in regs if x.name == el), None) self.args.append(reg_comp) + self.size += 1 + continue else: - # directly append the immediate - self.args.append(VMComponent(el, el)) + # section + sec_comp = next((x for x in sections if x.name == el), None) + if sec_comp: + self.args.append(VMComponent( + sec_comp.name, sec_comp.offset)) + self.size += 2 + continue + raise AssemblerException() def __repr__(self): return "{} {}".format(self.opcode.name, ", ".join([x.name for x in self.args])) + +class VMSection: + """ + Represents a code section or "label" such as "main:" + """ + + def __init__(self, name): + self.name = name + self.size = 0 + self.offset = 0 + + def set_size(self, size): + self.size = size + + def set_offset(self, offset): + self.offset = offset + + def __repr__(self): + return "{} | s: {}, o: {}".format(self.name, hex(self.size), hex(self.offset)) + op_names = [["MOVI", "imm2reg"], ["MOVR", "reg2reg"], ["LOAD", "imm2reg"], @@ -299,30 +350,54 @@ op_names = [["MOVI", "imm2reg"], ["POOP", "regonly"], ["CMPI", "imm2reg"], ["CMPR", "reg2reg"], - ["JMPI", "immonly"], - ["JMPR", "regonly"], - ["JPAI", "immonly"], - ["JPAR", "regonly"], - ["JPBI", "immonly"], - ["JPBR", "regonly"], - ["JPEI", "immonly"], - ["JPER", "regonly"], - ["JPNI", "immonly"], - ["JPNR", "regonly"], + ["JMPI", "jump"], + ["JMPR", "jump"], + ["JPAI", "jump"], + ["JPAR", "jump"], + ["JPBI", "jump"], + ["JPBR", "jump"], + ["JPEI", "jump"], + ["JPER", "jump"], + ["JPNI", "jump"], + ["JPNR", "jump"], ["SHIT", "single"], ["NOPE", "single"], ["GRMN", "single"]] reg_names = ["R0", "R1", "R2", "R3", "S0", "S1", "S2", "S3", "IP", "BP", "SP"] -section_names = ["DATA:", "CODE:", "STACK:"] -section_flags = {s.casefold(): i + 1 for i, s in enumerate(section_names)} ops = [VMComponent(le[0], i, le[1]) for i, le in enumerate(op_names)] regs = [VMComponent(s.casefold(), i) for i, s in enumerate(reg_names)] +sections = [] +section_re = re.compile("[a-zA-Z]*\:$") +immediate_re = re.compile("^[0-9].*") +register_re = re.compile("(^[rRsS]{1}[0-9]{1}$)|([iIbBsS]{1}[pP]{1}$)") -def assemble_data(line): - sys.stdout.write("DATA:\t") - sys.stdout.write(line.strip(",") + "\n") +def parse_sections(lines): + current_size = 0 + current_section = None + for line in lines: + if section_re.match(line): + if current_section: + tmp = next(x for x in sections if x.name == current_section) + tmp.set_size(current_size) + current_section = line.casefold()[:-1] + sections.append(VMSection(current_section)) + current_size = 0 + continue + components = [x for x in re.split('\W', line) if x] + instruction = VMInstruction(components[0], components[1:]) + current_size += instruction.size + tmp = next(x for x in sections if x.name == current_section) + tmp.set_size(current_size) + + +def calc_section_offsets(): + current_offset = 0 + for i in range(1, len(sections)): + prev_size = sections[i - 1].size + current_offset += prev_size + sections[i].set_offset(current_offset) def main(): @@ -330,22 +405,25 @@ def main(): print("Usage: {} opcodes_key file_to_assemble output".format( sys.argv[0])) return + vma = VMAssembler(sys.argv[1]) with open(sys.argv[2], 'r') as f: - gen = (line.casefold().strip() for line in f if line != "\n") - flag = None + filedata = f.readlines() + filedata = [x.strip() for x in filedata if x.strip()] + + # let's parse the whole file for labels + parse_sections(filedata) + + if "main" not in [x.name for x in sections]: + sys.stderr.write("No main specified!") + return + + calc_section_offsets() + + for line in filedata: + if not section_re.match(line): + vma.process_code_line(line) - for line in gen: - if line in section_flags: - flag = section_flags[line] - continue - if flag == section_flags["data:"]: - vma.process_code_line(line) - elif flag == section_flags["code:"]: - vma.process_code_line(line) - if not flag: - sys.stderr.write( - "Nothing was assembled! Did you use the section delimiters?\n") with open(sys.argv[3], 'wb') as f: f.write(vma.assembled_code)