Epreuve2 Version 2 (Gestion des DB)
This commit is contained in:
parent
f28819d288
commit
ea5f707d05
@ -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
178
Epreuve2.py
Normal 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.")
|
||||
@ -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
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user