Epreuve2 Version 2 (Gestion des DB)

This commit is contained in:
BalkisJerad 2026-03-22 00:16:34 +01:00
parent f28819d288
commit ea5f707d05
3 changed files with 186 additions and 6 deletions

View File

@ -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

178
Epreuve2.py Normal file
View File

@ -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 <file.asm>")
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.")

View File

@ -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