From ea5f707d05694532ca14f30c5ecc23fd4f520c3d Mon Sep 17 00:00:00 2001 From: BalkisJerad Date: Sun, 22 Mar 2026 00:16:34 +0100 Subject: [PATCH] Epreuve2 Version 2 (Gestion des DB) --- Epreuve2.asm | 7 +- Epreuve2.py | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++ Epreuve3.py | 7 +- 3 files changed, 186 insertions(+), 6 deletions(-) create mode 100644 Epreuve2.py diff --git a/Epreuve2.asm b/Epreuve2.asm index 4d83bed..9d5af54 100644 --- a/Epreuve2.asm +++ b/Epreuve2.asm @@ -4,10 +4,14 @@ _main: MOV R1 1 ; b OUT R0 ; print 0 +_data1: + DB 0 ;00000000 + DB 'C' ;01000011 + _loop: OUT R1 ; print b MOV R2 0 ; 0 - MOV R3 R0 ; c = a +MOV R3 R0 ; c = a SUB R2 R1 ; 0 - b SUB R3 R2 ; a - (0 - b) = a - -b = a + b @@ -19,4 +23,5 @@ _loop: JMP _loop _end: + LDR R2 R3 _data1 RET \ No newline at end of file diff --git a/Epreuve2.py b/Epreuve2.py new file mode 100644 index 0000000..3acbc57 --- /dev/null +++ b/Epreuve2.py @@ -0,0 +1,178 @@ +import sys + +# --- Configuration des instructions (Inchangée) --- +instructions = { + "DB": {"ins": "DB", "args": [{"isRegister": False, "isValue": True, "isLabel": False}]}, + "CALL": {"ins": "CALL", "args": [{"isRegister": False, "isValue": False, "isLabel": True}]}, + "RET": {"ins": "RET", "args": []}, + "JMP": {"ins": "JMP", "args": [{"isRegister": False, "isValue": False, "isLabel": True}]}, + "JLT": {"ins": "JLT", "args": [{"isRegister": False, "isValue": False, "isLabel": True}]}, + "JEQ": {"ins": "JEQ", "args": [{"isRegister": False, "isValue": False, "isLabel": True}]}, + "PUSH": {"ins": "PUSH", "args": [{"isRegister": True, "isValue": False, "isLabel": False}]}, + "POP": {"ins": "POP", "args": [{"isRegister": True, "isValue": False, "isLabel": False}]}, + "MOV": {"ins": "MOV", "args": [{"isRegister": True, "isValue": False, "isLabel": False}, {"isRegister": True, "isValue": True, "isLabel": False}]}, + "SUB": {"ins": "SUB", "args": [{"isRegister": True, "isValue": False, "isLabel": False}, {"isRegister": True, "isValue": True, "isLabel": False}]}, + "CMP": {"ins": "CMP", "args": [{"isRegister": True, "isValue": False, "isLabel": False}, {"isRegister": True, "isValue": True, "isLabel": False}]}, + "LDR": {"ins": "LDR", "args": [{"isRegister": True, "isValue": False, "isLabel": False}, {"isRegister": True, "isValue": False, "isLabel": False}, {"isRegister": False, "isValue": False, "isLabel": True}]}, + "STR": {"ins": "STR", "args": [{"isRegister": True, "isValue": False, "isLabel": False}, {"isRegister": True, "isValue": False, "isLabel": False}, {"isRegister": False, "isValue": False, "isLabel": True}]}, + "OUT": {"ins": "OUT", "args": [{"isRegister": True, "isValue": False, "isLabel": False}]}, + "TIM": {"ins": "TIM", "args": [{"isRegister": False, "isValue": True, "isLabel": False}]} +} + +# --- Fonctions Utilitaires (Inchangées) --- +def valueToInt(arg): + try: return int(arg) + except: return ord(arg[1]) + +def registerToDec(reg): return int(reg[1]) + +def testArgIsRegister(arg): + if len(arg) != 2 or arg[0] != "R": return False + try: return 0 <= int(arg[1]) <= 3 + except: return False + +def testArgIsValue(arg): + try: + if 0 <= int(arg) <= 255: return True + except: pass + if len(arg) == 3 and arg[0] == arg[2] == "'": return True + return False + +def testArgIsLabel(arg, twoDotsIncluded=False): + if not arg or arg[0] != "_": return False + body = arg[1:-1] if twoDotsIncluded else arg[1:] + if twoDotsIncluded and arg[-1] != ":": return False + return all(c in "abcdefghijklmnopqrstuvwxyz0123456789_" for c in body) + +# --- Fonctions de Conversion (Inchangées) --- +def convertInsDB(args): return {"opcode": [valueToInt(args[0])], "is_db": True} +def convertInsCALL(args): return {"opcode": [0x00, "label"], "label": args[0]} +def convertInsRET(args): return {"opcode": [0x80]} +def convertInsJMP(args): return {"opcode": [0x40, "label"], "label": args[0]} +def convertInsJLT(args): return {"opcode": [0xC0, "label"], "label": args[0]} +def convertInsJEQ(args): return {"opcode": [0x20, "label"], "label": args[0]} +def convertInsPUSH(args): return {"opcode": [0xA0 | registerToDec(args[0])]} +def convertInsPOP(args): return {"opcode": [0x60 | registerToDec(args[0])]} +def convertInsMOV(args): + idReg0 = registerToDec(args[0]) + if testArgIsRegister(args[1]): return {"opcode": [0x50 | (idReg0 << 2) | registerToDec(args[1])]} + return {"opcode": [0xE0 | idReg0, valueToInt(args[1])]} +def convertInsSUB(args): + idReg0 = registerToDec(args[0]) + if testArgIsRegister(args[1]): return {"opcode": [0xD0 | (idReg0 << 2) | registerToDec(args[1])]} + return {"opcode": [0x10 | idReg0, valueToInt(args[1])]} +def convertInsCMP(args): + idReg0 = registerToDec(args[0]) + if testArgIsRegister(args[1]): return {"opcode": [0x30 | (idReg0 << 2) | registerToDec(args[1])]} + return {"opcode": [0x90 | idReg0, valueToInt(args[1])]} +def convertInsLDR(args): + return {"opcode": [0xB0 | (registerToDec(args[0]) << 2) | registerToDec(args[1]), "label"], "label": args[2]} +def convertInsSTR(args): + return {"opcode": [0x70 | (registerToDec(args[0]) << 2) | registerToDec(args[1]), "label"], "label": args[2]} +def convertInsOUT(args): return {"opcode": [0xF0 | registerToDec(args[0])]} +def convertInsTIM(args): return {"opcode": [0xF8, valueToInt(args[0])]} + +# --- Assembleur --- +def assemble(path): + labels = {} + code_elements = [] + data_elements = [] + + with open(path, "r") as f: + lines = f.readlines() + + current_pending_labels = [] + + for line_num, line in enumerate(lines, 1): + line = line.split(";")[0].strip() + if not line: continue + + parts = line.split() + + # Traitement des labels (on peut en avoir plusieurs de suite) + while parts and testArgIsLabel(parts[0], True): + label_name = parts[0][:-1] + current_pending_labels.append(label_name) + parts = parts[1:] # On retire le label et on continue sur la même ligne + + if not parts: continue # Ligne ne contenait que des labels + + instr_name = parts[0] + args = parts[1:] + + try: + res = globals()[f"convertIns{instr_name}"](args) + res["attached_labels"] = current_pending_labels + current_pending_labels = [] + + if res.get("is_db"): + data_elements.append(res) + else: + code_elements.append(res) + except Exception as e: + print(f"ERROR Line {line_num}: {instr_name} -> {e}") + sys.exit(1) + + # Si des labels traînent à la toute fin du fichier + if current_pending_labels: + # On les attache à un élément factice à la fin de la data + data_elements.append({"opcode": [], "attached_labels": current_pending_labels, "is_db": True}) + + # CALCUL DES ADRESSES FINALES + final_labels = {} + current_pc = 0 + + # 1. On passe sur le CODE d'abord + for item in code_elements: + for lbl in item["attached_labels"]: + final_labels[lbl] = current_pc + current_pc += len(item["opcode"]) + + # 2. On passe sur la DATA ensuite + for item in data_elements: + for lbl in item["attached_labels"]: + final_labels[lbl] = current_pc + current_pc += len(item["opcode"]) + + # GÉNÉRATION DU BYTECODE + final_bytecode = [] + # Ordre : Code puis Data + for item in code_elements + data_elements: + for op in item["opcode"]: + if op == "label": + label_target = item["label"] + if label_target not in final_labels: + print(f"ERROR: Label '{label_target}' missing!") + sys.exit(1) + final_bytecode.append(final_labels[label_target]) + else: + final_bytecode.append(op) + + return final_bytecode, final_labels + +if __name__ == "__main__": + if len(sys.argv) < 2: + print("Usage: python asm.py ") + sys.exit(1) + + path = sys.argv[1] + bytecode, labels_map = assemble(path) + + # Affichage propre + print("\n" + "="*50) + print(f" ASSEMBLY PREVIEW: {path}") + print("="*50) + print(f"{'ADDR':<7} | {'HEX':<5} | {'BINARY':<10}") + print("-" * 30) + for i, b in enumerate(bytecode): + # On cherche si un label pointe ici pour l'afficher + lbl_str = "" + for name, addr in labels_map.items(): + if addr == i: lbl_str += f" ({name})" + + print(f"0x{i:02X} | {b:02x} | {b:08b} {lbl_str}") + print("="*50 + "\n") + + with open(path + ".bin", "wb") as file: + file.write(bytes(bytecode)) + print(f"Success: {path}.bin generated.") diff --git a/Epreuve3.py b/Epreuve3.py index 68ca609..ff4d2f4 100644 --- a/Epreuve3.py +++ b/Epreuve3.py @@ -69,10 +69,6 @@ class Simulator: size = 1 # taille en octets (1 ou 2) extra_cycles = 0 # pour LDR/STR/TIM - # --- instructions 2 octets à opcode fixe --- - #if c.after_ret: - # instr = f"DB 0x{b:02X}" - if b == 0x00: # CALL _label addr = self.fetch_byte() size = 2 @@ -204,8 +200,9 @@ class Simulator: pause_ms = mult * (v + 1) c.cycles += pause_ms # modélisation de la pause - else: + else: # Si DB est apres RET on n atteind pas ce bloc instr = f"DB 0x{b:02X}" + size = 0 # DB n'est pas une INS # instr = f"UNKNOWN 0x{b:02X}" # c.running = False