-
Notifications
You must be signed in to change notification settings - Fork 22
/
disasm.py
executable file
·84 lines (66 loc) · 2.5 KB
/
disasm.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/usr/bin/env python
from __future__ import print_function
import struct
import sys
import argparse
INSTRUCTIONS = [None, "SET", "ADD", "SUB", "MUL", "DIV", "MOD", "SHL", "SHR", "AND", "BOR", "XOR", "IFE", "IFN", "IFG", "IFB"]
IDENTIFERS = ["A", "B", "C", "X", "Y", "Z", "I", "J", "POP", "PEEK", "PUSH", "SP", "PC", "O"]
class Disassembler:
def __init__(self, program, output=sys.stdout):
self.program = program
self.offset = 0
self.output = output
def next_word(self):
w = self.program[self.offset]
self.offset += 1
return w
def format_operand(self, operand):
if operand < 0x08:
return "%s" % IDENTIFERS[operand]
elif operand < 0x10:
return "[%s]" % IDENTIFERS[operand % 0x08]
elif operand < 0x18:
return "[0x%02x + %s]" % (self.next_word(), IDENTIFERS[operand % 0x10])
elif operand < 0x1E:
return "%s" % IDENTIFERS[operand % 0x10]
elif operand == 0x1E:
return "[0x%02x]" % self.next_word()
elif operand == 0x1F:
return "0x%02x" % self.next_word()
else:
return "0x%02x" % (operand % 0x20)
def next_instruction(self):
offset = self.offset
w = self.next_word()
operands, opcode = divmod(w, 16)
b, a = divmod(operands, 64)
if opcode == 0x00:
if a == 0x01:
first = "JSR"
else:
return
else:
first = "%s %s," % (INSTRUCTIONS[opcode], self.format_operand(a))
asm = "%s %s" % (first, self.format_operand(b))
binary = " ".join("%04x" % word for word in self.program[offset:self.offset])
return "%-40s ; %04x: %s" % (asm, offset, binary)
def run(self):
while self.offset < len(self.program):
print(self.next_instruction(), file=self.output)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="DCPU-16 disassembler")
parser.add_argument("-o", help="Place the output into FILE instead of stdout", metavar="FILE")
parser.add_argument("input", help="File with DCPU object code")
args = parser.parse_args()
program = []
if args.input == "-":
f = sys.stdin
else:
f = open(args.input, "rb")
word = f.read(2)
while word:
program.append(struct.unpack(">H", word)[0])
word = f.read(2)
output = sys.stdout if args.o is None else open(args.o, "w")
d = Disassembler(program, output=output)
d.run()