Implement labels in assembler
This commit is contained in:
parent
d8f472a31f
commit
2982d12588
28
asm.py
28
asm.py
@ -122,13 +122,35 @@ def assemble_instruction(source, tokens):
|
||||
if argstr.startswith('R'):
|
||||
# Register
|
||||
arg = OpRegister(int(argstr[1:]))
|
||||
elif argstr.startswith('$'):
|
||||
# Label
|
||||
arg = OpLabel(argstr[1:])
|
||||
else:
|
||||
# Hex literal
|
||||
arg = OpLiteral(int(argstr, 16))
|
||||
instruction.args.append(arg)
|
||||
return [instruction], []
|
||||
|
||||
# TODO: First pass
|
||||
# First pass
|
||||
labels = {}
|
||||
SYN_MEM = [0] * 32768
|
||||
SYN_PTR = 0
|
||||
|
||||
with open(args.file, 'r') as source:
|
||||
try:
|
||||
while True:
|
||||
instructions, inst_labels = assemble_next_instruction(source)
|
||||
for label in inst_labels:
|
||||
if label.startswith('$'):
|
||||
labels[label[1:]] = SYN_PTR
|
||||
if instructions is None:
|
||||
break
|
||||
for instruction in instructions:
|
||||
code = instruction.assemble(None)
|
||||
SYN_MEM[SYN_PTR:SYN_PTR+len(code)] = code
|
||||
SYN_PTR += len(code)
|
||||
except Exception as ex:
|
||||
raise Exception('Error at line {}'.format(line_no)) from ex
|
||||
|
||||
# Second pass
|
||||
SYN_MEM = [0] * 32768
|
||||
@ -137,11 +159,11 @@ SYN_PTR = 0
|
||||
with open(args.file, 'r') as source:
|
||||
try:
|
||||
while True:
|
||||
instructions, labels = assemble_next_instruction(source)
|
||||
instructions, inst_labels = assemble_next_instruction(source)
|
||||
if instructions is None:
|
||||
break
|
||||
for instruction in instructions:
|
||||
code = instruction.assemble()
|
||||
code = instruction.assemble(labels)
|
||||
SYN_MEM[SYN_PTR:SYN_PTR+len(code)] = code
|
||||
SYN_PTR += len(code)
|
||||
except Exception as ex:
|
||||
|
@ -172,7 +172,10 @@ while SYN_PTR < len(SYN_MEM):
|
||||
loc = op.get(None)
|
||||
if any(v == loc for k, v in labels.items()):
|
||||
label = next(k for k, v in labels.items() if v == loc)
|
||||
print('{:04x}: {: <4} ${}'.format(SYN_PTR, instruction.name, label))
|
||||
if isinstance(instruction, InstructionJmp) or isinstance(instruction, InstructionCall):
|
||||
print('{:04x}: {: <4} ${}'.format(SYN_PTR, instruction.name, label))
|
||||
else:
|
||||
print('{:04x}: {: <4} {} ${}'.format(SYN_PTR, instruction.name, instruction.args[0].describe(), label))
|
||||
else:
|
||||
print('{:04x}: {}'.format(SYN_PTR, instruction.describe()))
|
||||
else:
|
||||
|
@ -33,7 +33,7 @@ class OpLiteral(Operand):
|
||||
|
||||
def describe(self):
|
||||
return '{:04x}'.format(self.value)
|
||||
def assemble(self):
|
||||
def assemble(self, labels):
|
||||
return self.value
|
||||
|
||||
class OpRegister(Operand):
|
||||
@ -46,9 +46,22 @@ class OpRegister(Operand):
|
||||
|
||||
def describe(self):
|
||||
return 'R{}'.format(self.register)
|
||||
def assemble(self):
|
||||
def assemble(self, labels):
|
||||
return self.register + 32768
|
||||
|
||||
# Used only in assembling process
|
||||
class OpLabel(Operand):
|
||||
def __init__(self, label):
|
||||
self.label = label
|
||||
|
||||
def assemble(self, labels):
|
||||
if labels is None:
|
||||
# First pass
|
||||
return 0xffff
|
||||
if self.label not in labels:
|
||||
raise Exception('Unknown label {}'.format(self.label))
|
||||
return OpLiteral(labels[self.label]).assemble(labels)
|
||||
|
||||
instructions_by_opcode = {}
|
||||
instructions_by_name = {}
|
||||
|
||||
@ -74,8 +87,8 @@ class Instruction:
|
||||
description += ' {}'.format(self.args[i].describe())
|
||||
return description
|
||||
|
||||
def assemble(self):
|
||||
return [self.opcode] + [self.args[i].assemble() for i in range(self.nargs)]
|
||||
def assemble(self, labels):
|
||||
return [self.opcode] + [self.args[i].assemble(labels) for i in range(self.nargs)]
|
||||
|
||||
@staticmethod
|
||||
def next_instruction(data, idx):
|
||||
@ -228,6 +241,6 @@ class InstructionIn(Instruction):
|
||||
# Not actually an instruction, but convenient to think of it as one for the purposes of assembling
|
||||
# self.args is an array of literal values, rather than Operands
|
||||
class InstructionData(Instruction):
|
||||
def assemble(self):
|
||||
def assemble(self, labels):
|
||||
return self.args
|
||||
instructions_by_name['data'] = InstructionData
|
||||
|
Reference in New Issue
Block a user