1
0
mirror of https://github.com/rzzzwilson/pymlac.git synced 2025-06-10 09:32:41 +00:00

Start assembling actual instructions

This commit is contained in:
Ross Wilson
2016-01-27 10:46:56 +07:00
parent 6fff1b7f46
commit 49c09b3b1e

View File

@@ -50,6 +50,9 @@ OutputFileHandle = None # open output file
# the program start address (optional)
StartAddr = None
# the current address in assembled code (dot)
Address = None
# the symbol table(s)
# {<name>: <value>, ... }
SymTable = {}
@@ -139,12 +142,12 @@ def eval_expression(expr, dot):
# replace any "." value with "dot" defined in the symbol table
expr = string.replace(expr, '.', 'dot')
expr = expr.upper()
env = copy.deepcopy(SymTable)
env['DOT'] = dot # add in the "." address
globs = copy.deepcopy(SymTable)
globs['DOT'] = dot # add in the "." address
# evaluate the expression
try:
result = eval(expr, env)
result = eval(expr, globs)
except TypeError as e:
error('ORG pseudo-opcode expression contains unsatisfied references\n'
'%d: %s' % (CurrentLineNumber, CurrentLine))
@@ -183,9 +186,11 @@ def gen_ascii(string, address, lnum, line):
"""Generate data words for ASCII string.
string the string to generate data for
address 'dot' value for first word generated
address addres of first generated word (dot)
lnum line number of code
line actual line of code
Returns the updated 'dot' value.
"""
# ensure even number of bytes in string
@@ -203,6 +208,8 @@ def gen_ascii(string, address, lnum, line):
lnum = None
line = None
return address
def assemble_oblock(oblock):
"""Assemble one org block to a code block.
@@ -210,7 +217,7 @@ def assemble_oblock(oblock):
A code block: [address, [word, word, word, ...]]
"""
global CurrentLineNumber, CurrentLine
global CurrentLineNumber, CurrentLine, Address
cblock = [None, []]
@@ -219,14 +226,14 @@ def assemble_oblock(oblock):
return cblock
# assemble the org block
address = None # '.' value
# address = None # '.' value
for (lnum, line, label, opcode, addr) in oblock:
CurrentLineNumber = lnum
CurrentLine = line
# if no code, just list it
if label is None and opcode is None:
write_list(None, None, lnum, line)
write_list(label, opcode, lnum, line)
else:
# maybe we have some code to generate
if opcode:
@@ -236,11 +243,11 @@ def assemble_oblock(oblock):
error('%d: %s\nORG opcode may not have a label'
% (lnum, line))
try:
address = eval_expression(addr, address)
Address = eval_expression(addr, Address)
except NameError as e:
error("%d: %s\nName '%s' is undefined"
% (lnum, line, Undefined))
cblock = [address, []]
cblock = [Address, []]
write_list(None, None, lnum, line)
continue
elif opcode == 'END':
@@ -248,7 +255,7 @@ def assemble_oblock(oblock):
start_addr = None
if addr:
try:
start_addr = eval_expression(addr, address)
start_addr = eval_expression(addr, Address)
except NameError as e:
error("%d: %s\nName '%s' is undefined"
% (lnum, line, undefined))
@@ -259,7 +266,7 @@ def assemble_oblock(oblock):
error('%d: %s\nEQU opcode missing a label'
% (lnum, line))
try:
value = eval_expression(addr, None)
value = eval_expression(addr, Address)
except NameError as e:
error("%d: %s\nName '%s' is undefined"
% (lnum, line, Undefined))
@@ -268,27 +275,26 @@ def assemble_oblock(oblock):
continue
elif opcode == 'DATA':
try:
value = eval_expression(addr, address)
value = eval_expression(addr, Address)
except NameError as e:
error("%d: %s\nName '%s' is undefined"
% (lnum, line, Undefined))
ln = lnum
li = line
if isinstance(value, basestring):
gen_ascii(value, address, lnum, line)
Address = gen_ascii(value, Address, lnum, line)
else:
write_list(value, address, lnum, line)
address += 1
write_list(value, Address, lnum, line)
Address += 1
else:
code = assemble_line(lnum, opcode, addr)
cblock[1].append((code, addr))
write_list(code, address, lnum, line)
write_list(code, Address, lnum, line)
if label:
define_label(label, address, lnum)
address += 1
define_label(label, Address, lnum)
Address += 1
elif label:
# we have a label and no opcode, just define the label and list it
define_label(label, address, lnum)
define_label(label, Address, lnum)
write_list(None, None, lnum, line)
return cblock
@@ -387,7 +393,7 @@ def split_orgs(asm_lines):
CurrentLineNumber = lnum
CurrentLine = line
if opcode:
if opcode.lower() == 'org':
if opcode == 'ORG':
if block:
# save previous ORG block
result.append(block)
@@ -407,12 +413,14 @@ def split_orgs(asm_lines):
def check_org_overlap(code_blocks):
"""Check that we don't have overlapping ORG blocks."""
global Address
# remember org block span: [(start, end), (start', end'), ...]
block_span = []
for cb in code_blocks:
(address, code) = cb
if address is None and not code:
(Address, code) = cb
if Address is None and not code:
# empty code block, ignore
continue
(block_start, code) = cb
@@ -465,7 +473,7 @@ def backpatch(code_blocks):
return [address, new_code]
def assemble_file():
"""Assemble the file and produce listing, output files."""
"""Assemble the file and produce listing & output files."""
# read all of ASM file into memory, strip \n, etc
with open(AsmFile, 'rb') as fd:
@@ -474,20 +482,27 @@ def assemble_file():
print('asm_lines=\n%s' % '\n'.join(asm_lines))
org_blocks = split_orgs(asm_lines)
print('org_blocks=%s' % str(org_blocks))
for (n, ob) in enumerate(org_blocks):
print('Block %d:' % n)
for e in ob:
print('\t%s' % str(e))
code_blocks = assemble_org_blocks(org_blocks)
print('code_blocks=%s' % str(code_blocks))
for (n, cb) in enumerate(code_blocks):
print('Code block %d: Address=%s, code=%s' % (n, str(cb[0]), str(cb[1])))
print('SymTable=%s' % str(SymTable))
print('SymTableLine=%s' % str(SymTableLine))
# allow programmer to overlap ORG blocks
# check_org_overlap(code_blocks)
allocate_literals(code_blocks)
# allocate_literals(code_blocks)
patched_code_blocks = backpatch(code_blocks)
print('patched_code_blocks=%s' % str(patched_code_blocks))
# for (n, pb) in enumerate(patched_code_blocks):
# print('Patched %d:' % n)
# print('\t%s' % str(pb))
def main():
"""The assembler."""