Add label processing to disassembler

This commit is contained in:
RunasSudo 2017-02-13 19:06:53 +10:30
parent 81039ce304
commit d8f472a31f
Signed by: RunasSudo
GPG Key ID: 7234E476BF21C61A
3 changed files with 191 additions and 1 deletions

View File

@ -21,11 +21,61 @@ import argparse
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('file', help='.bin file containing the initial memory dump') parser.add_argument('file', help='.bin file containing the initial memory dump')
parser.add_argument('--hints', help='File(s) outlining additional jmp/call targets, label names, comments, etc', action='append')
args = parser.parse_args() args = parser.parse_args()
with open(args.file, 'rb') as data: with open(args.file, 'rb') as data:
SYN_MEM = memory_from_file(data) SYN_MEM = memory_from_file(data)
# Find things to label
labels, comments_before, comments_inline = {}, {}, {}
SYN_PTR = 0
while SYN_PTR < len(SYN_MEM):
word = SYN_MEM[SYN_PTR]
if word in instructions_by_opcode:
instruction, SYN_PTR = Instruction.next_instruction(SYN_MEM, SYN_PTR)
if isinstance(instruction, InstructionJmp) or isinstance(instruction, InstructionJt) or isinstance(instruction, InstructionJf):
if isinstance(instruction, InstructionJmp):
op = instruction.args[0]
else:
op = instruction.args[1]
if isinstance(op, OpLiteral):
loc = op.get(None)
labels['label_{:04x}'.format(loc)] = loc
elif isinstance(instruction, InstructionCall):
if isinstance(instruction.args[0], OpLiteral):
loc = instruction.args[0].get(None)
labels['sub_{:04x}'.format(loc)] = loc
else:
SYN_PTR += 1
# Read hints
if args.hints:
for hintfile in args.hints:
with open(hintfile, 'r') as data:
while True:
line = data.readline()
if line == '':
break
if line.startswith('jmp '):
loc = int(line.split()[1], 16)
labels['label_{:04x}'.format(loc)] = loc
elif line.startswith('call '):
loc = int(line.split()[1], 16)
labels['sub_{:04x}'.format(loc)] = loc
elif line.startswith('ren '):
old_label = line.split()[1]
new_label = line.split()[2]
labels[new_label] = labels[old_label]
del labels[old_label]
elif line.startswith('cmb '):
loc = int(line.split()[1], 16)
comment = line[line.index(' ', line.index(' ') + 1) + 1:].strip()
if loc not in comments_before:
comments_before[loc] = []
comments_before[loc].append(comment)
else:
raise Exception('Invalid line in hint file: {}'.format(line))
def escape_char(char): def escape_char(char):
return char.encode('unicode_escape').decode('utf-8').replace('"', '\\"') return char.encode('unicode_escape').decode('utf-8').replace('"', '\\"')
@ -35,6 +85,30 @@ MODE_DAT = False #False, 1 (data), 2 (text)
SYN_PTR = 0 SYN_PTR = 0
while SYN_PTR < len(SYN_MEM): while SYN_PTR < len(SYN_MEM):
if SYN_PTR in comments_before:
if MODE_OUT:
print('"')
MODE_OUT = False
if MODE_DAT == 1:
print()
MODE_DAT = False
if MODE_DAT == 2:
print('"')
MODE_DAT = False
for comment in comments_before[SYN_PTR]:
print('; {}'.format(comment))
if any(v == SYN_PTR for k, v in labels.items()):
if MODE_OUT:
print('"')
MODE_OUT = False
if MODE_DAT == 1:
print()
MODE_DAT = False
if MODE_DAT == 2:
print('"')
MODE_DAT = False
print('${}:'.format(next(k for k, v in labels.items() if v == SYN_PTR)))
word = SYN_MEM[SYN_PTR] word = SYN_MEM[SYN_PTR]
if MODE_OUT and word != 19: if MODE_OUT and word != 19:
@ -72,7 +146,7 @@ while SYN_PTR < len(SYN_MEM):
SYN_PTR += 1 SYN_PTR += 1
else: else:
# Instruction # Instruction
instruction, SYN_PTR = Instruction.next_instruction(SYN_MEM, SYN_PTR) instruction, next_SYN_PTR = Instruction.next_instruction(SYN_MEM, SYN_PTR)
# Special cases # Special cases
if isinstance(instruction, InstructionOut): if isinstance(instruction, InstructionOut):
if isinstance(instruction.args[0], OpLiteral): if isinstance(instruction.args[0], OpLiteral):
@ -89,5 +163,20 @@ while SYN_PTR < len(SYN_MEM):
print('"') print('"')
MODE_OUT = False MODE_OUT = False
print('{:04x}: {}'.format(SYN_PTR, instruction.describe())) print('{:04x}: {}'.format(SYN_PTR, instruction.describe()))
elif isinstance(instruction, InstructionJmp) or isinstance(instruction, InstructionJt) or isinstance(instruction, InstructionJf) or isinstance(instruction, InstructionCall):
if isinstance(instruction, InstructionJmp) or isinstance(instruction, InstructionCall):
op = instruction.args[0]
else:
op = instruction.args[1]
if isinstance(op, OpLiteral):
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))
else: else:
print('{:04x}: {}'.format(SYN_PTR, instruction.describe())) print('{:04x}: {}'.format(SYN_PTR, instruction.describe()))
else:
print('{:04x}: {}'.format(SYN_PTR, instruction.describe()))
else:
print('{:04x}: {}'.format(SYN_PTR, instruction.describe()))
SYN_PTR = next_SYN_PTR

View File

@ -0,0 +1,6 @@
jmp 0000
ren label_0000 start
jmp 0110
ren label_0110 self_test
cmb 0140 Test jmp
ren label_015b self_test_jmp1

95
disasm_hints/jmpcall.txt Normal file
View File

@ -0,0 +1,95 @@
call 0505
call 0507
call 05b2
call 05ee
call 05f8
call 05fb
call 0607
call 0623
call 0634
call 0645
call 0653
call 0670
call 0683
call 06bb
call 06e7
call 0731
call 07d1
call 084d
call 0865
call 086e
call 0882
call 08c8
call 08e9
call 0b94
call 0cad
call 0d48
call 0df0
call 0e48
call 0e8f
call 0e9e
call 0ec0
call 0eca
call 0ede
call 0f35
call 0f98
call 0fa9
call 0fcd
call 0fde
call 1000
call 1011
call 1022
call 1033
call 1044
call 107a
call 10b7
call 1135
call 11a3
call 11b5
call 1203
call 1252
call 1270
call 12bf
call 1315
call 1371
call 14f0
call 1501
call 1512
call 1523
call 1534
call 1545
call 1659
call 16b6
call 16bf
call 16d6
call 16f4
call 1705
call 1721
call 174c
call 1766
jmp 015b
jmp 0166
jmp 01e4
jmp 02c4
jmp 02db
jmp 034d
jmp 03e8
jmp 061e
jmp 06b2
jmp 06fb
jmp 07e3
jmp 07ff
jmp 0833
jmp 08bc
jmp 08cc
jmp 08f8
jmp 0aae
jmp 0b86
jmp 0c79
jmp 0cfe
jmp 0d99
jmp 0e43
jmp 112e
jmp 1312
jmp 1652
jmp 1747