mirror of
https://github.com/mnaberez/py65.git
synced 2025-04-05 13:37:09 +00:00
Added disassembler.
This commit is contained in:
parent
fda4631664
commit
469a822a37
169
src/py65/disassembler.py
Normal file
169
src/py65/disassembler.py
Normal file
@ -0,0 +1,169 @@
|
||||
class Disassembler:
|
||||
_instructions = [
|
||||
['BRK','imp'], ['ORA','inx'], ['???','imp'], ['???','imp'],
|
||||
['???','imp'], ['ORA','zpg'], ['ASL','zpg'], ['???','imp'],
|
||||
['PHP','imp'], ['ORA','imm'], ['ASL','acc'], ['???','imp'],
|
||||
['???','imp'], ['ORA','abs'], ['ASL','abs'], ['???','imp'],
|
||||
['BPL','rel'], ['ORA','iny'], ['???','imp'], ['???','imp'],
|
||||
['???','imp'], ['ORA','zpx'], ['ASL','zpx'], ['???','imp'],
|
||||
['CLC','imp'], ['ORA','aby'], ['???','imp'], ['???','imp'],
|
||||
['???','imp'], ['ORA','abx'], ['ASL','abx'], ['???','imp'],
|
||||
['JSR','abs'], ['AND','inx'], ['???','imp'], ['???','imp'],
|
||||
['BIT','zpg'], ['AND','zpg'], ['ROL','zpg'], ['???','imp'],
|
||||
['PLP','imp'], ['AND','imm'], ['ROL','acc'], ['???','imp'],
|
||||
['BIT','abs'], ['AND','abs'], ['ROL','abs'], ['???','imp'],
|
||||
['BMI','rel'], ['AND','iny'], ['???','imp'], ['???','imp'],
|
||||
['???','imp'], ['AND','zpx'], ['ROL','zpx'], ['???','imp'],
|
||||
['SEC','imp'], ['AND','aby'], ['???','imp'], ['???','imp'],
|
||||
['???','imp'], ['AND','abx'], ['ROL','abx'], ['???','imp'],
|
||||
['RTI','imp'], ['EOR','inx'], ['???','imp'], ['???','imp'],
|
||||
['???','imp'], ['EOR','zpg'], ['LSR','zpg'], ['???','imp'],
|
||||
['PHA','imp'], ['EOR','imm'], ['LSR','acc'], ['???','imp'],
|
||||
['JMP','abs'], ['EOR','abs'], ['LSR','abs'], ['???','imp'],
|
||||
['BVC','rel'], ['EOR','iny'], ['???','imp'], ['???','imp'],
|
||||
['???','imp'], ['EOR','zpx'], ['LSR','zpx'], ['???','imp'],
|
||||
['CLI','imp'], ['EOR','aby'], ['???','imp'], ['???','imp'],
|
||||
['???','imp'], ['EOR','abx'], ['LSR','abx'], ['???','imp'],
|
||||
['RTS','imp'], ['ADC','inx'], ['???','imp'], ['???','imp'],
|
||||
['???','imp'], ['ADC','zpg'], ['ROR','zpg'], ['???','imp'],
|
||||
['PLA','imp'], ['ADC','imm'], ['ROR','acc'], ['???','imp'],
|
||||
['JMP','ind'], ['ADC','abs'], ['ROR','abs'], ['???','imp'],
|
||||
['BVS','rel'], ['ADC','iny'], ['???','imp'], ['???','imp'],
|
||||
['???','imp'], ['ADC','zpx'], ['ROR','zpx'], ['???','imp'],
|
||||
['SEI','imp'], ['ADC','aby'], ['???','imp'], ['???','imp'],
|
||||
['???','imp'], ['ADC','abx'], ['ROR','abx'], ['???','imp'],
|
||||
['???','imp'], ['STA','inx'], ['???','imp'], ['???','imp'],
|
||||
['STY','zpg'], ['STA','zpg'], ['STX','zpg'], ['???','imp'],
|
||||
['DEY','imp'], ['???','imp'], ['TXA','imp'], ['???','imp'],
|
||||
['STY','abs'], ['STA','abs'], ['STX','abs'], ['???','imp'],
|
||||
['BCC','rel'], ['STA','iny'], ['???','imp'], ['???','imp'],
|
||||
['STY','zpx'], ['STA','zpx'], ['STX','zpy'], ['???','imp'],
|
||||
['TYA','imp'], ['STA','aby'], ['TXS','imp'], ['???','imp'],
|
||||
['???','imp'], ['STA','abx'], ['???','imp'], ['???','imp'],
|
||||
['LDY','imm'], ['LDA','inx'], ['LDX','imm'], ['???','imp'],
|
||||
['LDY','zpg'], ['LDA','zpg'], ['LDX','zpg'], ['???','imp'],
|
||||
['TAY','imp'], ['LDA','imm'], ['TAX','imp'], ['???','imp'],
|
||||
['LDY','abs'], ['LDA','abs'], ['LDX','abs'], ['???','imp'],
|
||||
['BCS','rel'], ['LDA','iny'], ['???','imp'], ['???','imp'],
|
||||
['LDY','zpx'], ['LDA','zpx'], ['LDX','zpy'], ['???','imp'],
|
||||
['CLV','imp'], ['LDA','aby'], ['TSX','imp'], ['???','imp'],
|
||||
['LDY','abx'], ['LDA','abx'], ['LDX','aby'], ['???','imp'],
|
||||
['CPY','imm'], ['CMP','inx'], ['???','imp'], ['???','imp'],
|
||||
['CPY','zpg'], ['CMP','zpg'], ['DEC','zpg'], ['???','imp'],
|
||||
['INY','imp'], ['CMP','imm'], ['DEX','imp'], ['???','imp'],
|
||||
['CPY','abs'], ['CMP','abs'], ['DEC','abs'], ['???','imp'],
|
||||
['BNE','rel'], ['CMP','iny'], ['???','imp'], ['???','imp'],
|
||||
['???','imp'], ['CMP','zpx'], ['DEC','zpx'], ['???','imp'],
|
||||
['CLD','imp'], ['CMP','aby'], ['???','imp'], ['???','imp'],
|
||||
['???','imp'], ['CMP','abx'], ['DEC','abx'], ['???','imp'],
|
||||
['CPX','imm'], ['SBC','inx'], ['???','imp'], ['???','imp'],
|
||||
['CPX','zpg'], ['SBC','zpg'], ['INC','zpg'], ['???','imp'],
|
||||
['INX','imp'], ['SBC','imm'], ['NOP','imp'], ['???','imp'],
|
||||
['CPX','abs'], ['SBC','abs'], ['INC','abs'], ['???','imp'],
|
||||
['BEQ','rel'], ['SBC','iny'], ['???','imp'], ['???','imp'],
|
||||
['???','imp'], ['SBC','zpx'], ['INC','zpx'], ['???','imp'],
|
||||
['SED','imp'], ['SBC','aby'], ['???','imp'], ['???','imp'],
|
||||
['???','imp'], ['SBC','abx'], ['INC','abx'], ['???','imp']
|
||||
]
|
||||
|
||||
def __init__(self, mpu, address_parser):
|
||||
self._mpu = mpu
|
||||
self._address_parser = address_parser
|
||||
|
||||
def instruction_at(self, pc):
|
||||
""" Disassemble the instruction at PC and return a tuple
|
||||
containing (instruction byte count, human readable text)
|
||||
"""
|
||||
|
||||
instruction = self._mpu.ByteAt(pc)
|
||||
disasm, addressing = self._instructions[instruction]
|
||||
|
||||
if addressing == 'acc':
|
||||
disasm += ' A'
|
||||
|
||||
elif addressing == 'abs':
|
||||
address = self._mpu.WordAt(pc + 1)
|
||||
address_or_label = self._address_parser.label_for(address,
|
||||
'$%04x' % address)
|
||||
disasm += ' ' + address_or_label
|
||||
length = 3
|
||||
|
||||
elif addressing == 'abx':
|
||||
address = self._mpu.WordAt(pc + 1)
|
||||
address_or_label = self._address_parser.label_for(address,
|
||||
'$%04x' % address)
|
||||
disasm += ' %s,X' % address_or_label
|
||||
length = 3
|
||||
|
||||
elif addressing == 'aby':
|
||||
address = self._mpu.WordAt(pc + 1)
|
||||
address_or_label = self._address_parser.label_for(address,
|
||||
'$%04x' % address)
|
||||
disasm += ' %s,Y' % address_or_label
|
||||
length = 3
|
||||
|
||||
elif addressing == 'imm':
|
||||
byte = self._mpu.ByteAt(pc + 1)
|
||||
disasm += ' #$%02x' % byte
|
||||
length = 2
|
||||
|
||||
elif addressing == 'imp':
|
||||
length = 1
|
||||
|
||||
elif addressing == 'ind':
|
||||
address = self._mpu.WordAt(pc + 1)
|
||||
address_or_label = self._address_parser.label_for(address,
|
||||
'$%04x' % address)
|
||||
disasm += ' (%s)' % address_or_label
|
||||
length = 3
|
||||
|
||||
elif addressing == 'iny':
|
||||
zp_address = self._mpu.ByteAt(pc + 1)
|
||||
address_or_label = self._address_parser.label_for(zp_address,
|
||||
'$%02x' % zp_address)
|
||||
disasm += ' (%s),Y' % address_or_label
|
||||
length = 2
|
||||
|
||||
elif addressing == 'inx':
|
||||
zp_address = self._mpu.ByteAt(pc + 1)
|
||||
address_or_label = self._address_parser.label_for(zp_address,
|
||||
'$%02x' % zp_address)
|
||||
disasm += ' (%s,X)' % address_or_label
|
||||
length = 2
|
||||
|
||||
elif addressing == 'rel':
|
||||
opv = self._mpu.ByteAt(pc + 1)
|
||||
targ = pc + 2
|
||||
if opv & 128:
|
||||
targ -= (opv ^ 255) + 1
|
||||
else:
|
||||
targ += opv
|
||||
targ &= 0xffff
|
||||
|
||||
address_or_label = self._address_parser.label_for(targ,
|
||||
'$%04x' % targ)
|
||||
disasm += ' ' + address_or_label
|
||||
length = 2
|
||||
|
||||
elif addressing == 'zpg':
|
||||
zp_address = self._mpu.ByteAt(pc + 1)
|
||||
address_or_label = self._address_parser.label_for(zp_address,
|
||||
'$%02x' % zp_address)
|
||||
disasm += ' %s' % address_or_label
|
||||
length = 2
|
||||
|
||||
elif addressing == 'zpx':
|
||||
zp_address = self._mpu.ByteAt(pc + 1)
|
||||
address_or_label = self._address_parser.label_for(zp_address,
|
||||
'$%02x' % zp_address)
|
||||
disasm += ' %s,X' % address_or_label
|
||||
length = 2
|
||||
|
||||
elif addressing == 'zpy':
|
||||
zp_address = self._mpu.ByteAt(pc + 1)
|
||||
address_or_label = self._address_parser.label_for(zp_address,
|
||||
'$%02x' % zp_address)
|
||||
disasm += ' %s,Y' % address_or_label
|
||||
length = 2
|
||||
|
||||
return (length, disasm)
|
@ -7,6 +7,7 @@ import shlex
|
||||
import asyncore
|
||||
import sys
|
||||
from py65.mpu6502 import MPU
|
||||
from py65.disassembler import Disassembler
|
||||
from py65.util import itoa, AddressParser, getch
|
||||
from py65.memory import ObservableMemory
|
||||
|
||||
@ -18,6 +19,7 @@ class Monitor(cmd.Cmd):
|
||||
self._install_mpu_observers()
|
||||
self._update_prompt()
|
||||
self._address_parser = AddressParser()
|
||||
self._disassembler = Disassembler(self._mpu, self._address_parser)
|
||||
cmd.Cmd.__init__(self, completekey, stdin, stdout)
|
||||
|
||||
def onecmd(self, line):
|
||||
@ -105,11 +107,34 @@ class Monitor(cmd.Cmd):
|
||||
def help_quit(self):
|
||||
return self.help_EOF()
|
||||
|
||||
def do_disassemble(self, args):
|
||||
start, end = self._address_parser.range(args)
|
||||
if start == end:
|
||||
end += 1
|
||||
|
||||
address = start
|
||||
while address < end:
|
||||
bytes, disasm = self._disassembler.instruction_at(address)
|
||||
|
||||
mem = ''
|
||||
for byte in self._mpu.memory[address:address+bytes]:
|
||||
mem += '%02x ' % byte
|
||||
|
||||
line = "$%04x %-10s%s" % (address, mem, disasm)
|
||||
self._output(line)
|
||||
|
||||
address += bytes
|
||||
|
||||
def help_disassemble(self):
|
||||
self._output("disassemble <address_range>")
|
||||
self._output("Disassemble instructions in the address range.")
|
||||
|
||||
def help_step(self):
|
||||
self._output("Single-step through instructions.")
|
||||
|
||||
def do_step(self, args):
|
||||
self._mpu.step()
|
||||
self.do_disassemble('%04x' % self._mpu.pc)
|
||||
|
||||
def help_return(self):
|
||||
self._output("Continues execution and returns to the monitor just")
|
||||
@ -119,6 +144,10 @@ class Monitor(cmd.Cmd):
|
||||
returns = [0x60, 0x40] # RTS, RTI
|
||||
self._run(stopcodes=returns)
|
||||
|
||||
def help_goto(self):
|
||||
self._output("goto <address>")
|
||||
self._output("Change the PC to address and continue execution.")
|
||||
|
||||
def do_goto(self, args):
|
||||
self._mpu.pc = self._address_parser.number(args)
|
||||
brks = [0x00] # BRK
|
||||
@ -295,6 +324,10 @@ class Monitor(cmd.Cmd):
|
||||
out += "%02x " % byte
|
||||
self._output(out)
|
||||
|
||||
def help_add_label(self):
|
||||
self._output("add_label <address> <label>")
|
||||
self._output("Map a given address to a label.")
|
||||
|
||||
def do_add_label(self, args):
|
||||
split = shlex.split(args)
|
||||
if len(split) != 2:
|
||||
@ -306,6 +339,10 @@ class Monitor(cmd.Cmd):
|
||||
|
||||
self._address_parser.labels[label] = address
|
||||
|
||||
def help_show_labels(self):
|
||||
self._output("show_labels")
|
||||
self._output("Display current label mappings.")
|
||||
|
||||
def do_show_labels(self, args):
|
||||
values = self._address_parser.labels.values()
|
||||
keys = self._address_parser.labels.keys()
|
||||
@ -315,6 +352,10 @@ class Monitor(cmd.Cmd):
|
||||
for address, label in byaddress:
|
||||
self._output("%04x: %s" % (address, label))
|
||||
|
||||
def help_delete_label(self):
|
||||
self._output("delete_label <label>")
|
||||
self._output("Remove the specified label from the label tables.")
|
||||
|
||||
def do_delete_label(self, args):
|
||||
try:
|
||||
del self._address_parser.labels[args]
|
||||
|
276
src/py65/tests/test_disassembler.py
Normal file
276
src/py65/tests/test_disassembler.py
Normal file
@ -0,0 +1,276 @@
|
||||
import unittest
|
||||
import sys
|
||||
from py65.mpu6502 import MPU
|
||||
from py65.disassembler import Disassembler
|
||||
from py65.util import AddressParser
|
||||
|
||||
class DisassemblerTests(unittest.TestCase):
|
||||
def test_disassembles_00(self):
|
||||
length, disasm = self.disassemble([0x00])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('BRK', disasm)
|
||||
|
||||
def test_disassembles_01(self):
|
||||
length, disasm = self.disassemble([0x01, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('ORA ($44,X)', disasm)
|
||||
|
||||
def test_disassembles_02(self):
|
||||
length, disasm = self.disassemble([0x02])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('???', disasm)
|
||||
|
||||
def test_disassembles_03(self):
|
||||
length, disasm = self.disassemble([0x03])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('???', disasm)
|
||||
|
||||
def test_disassembles_04(self):
|
||||
length, disasm = self.disassemble([0x04])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('???', disasm)
|
||||
|
||||
def test_disassembles_05(self):
|
||||
length, disasm = self.disassemble([0x05, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('ORA $44', disasm)
|
||||
|
||||
def test_disassembles_06(self):
|
||||
length, disasm = self.disassemble([0x06, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('ASL $44', disasm)
|
||||
|
||||
def test_disassembles_07(self):
|
||||
length, disasm = self.disassemble([0x07])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('???', disasm)
|
||||
|
||||
def test_disassembles_08(self):
|
||||
length, disasm = self.disassemble([0x08])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('PHP', disasm)
|
||||
|
||||
def test_disassembles_09(self):
|
||||
length, disasm = self.disassemble([0x09, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('ORA #$44', disasm)
|
||||
|
||||
def test_disassembles_10(self):
|
||||
length, disasm = self.disassemble([0x10, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('BPL $0046', disasm)
|
||||
|
||||
def test_disassembles_11(self):
|
||||
length, disasm = self.disassemble([0x11, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('ORA ($44),Y', disasm)
|
||||
|
||||
def test_disassembles_12(self):
|
||||
length, disasm = self.disassemble([0x12])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('???', disasm)
|
||||
|
||||
def test_disassembles_13(self):
|
||||
length, disasm = self.disassemble([0x13])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('???', disasm)
|
||||
|
||||
def test_disassembles_14(self):
|
||||
length, disasm = self.disassemble([0x14])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('???', disasm)
|
||||
|
||||
def test_disassembles_15(self):
|
||||
length, disasm = self.disassemble([0x15, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('ORA $44,X', disasm)
|
||||
|
||||
def test_disassembles_16(self):
|
||||
length, disasm = self.disassemble([0x16, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('ASL $44,X', disasm)
|
||||
|
||||
def test_disassembles_17(self):
|
||||
length, disasm = self.disassemble([0x17])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('???', disasm)
|
||||
|
||||
def test_disassembles_18(self):
|
||||
length, disasm = self.disassemble([0x18])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('CLC', disasm)
|
||||
|
||||
def test_disassembles_19(self):
|
||||
length, disasm = self.disassemble([0x19, 0x00, 0x44])
|
||||
self.assertEqual(3, length)
|
||||
self.assertEqual('ORA $4400,Y', disasm)
|
||||
|
||||
def test_disassembles_20(self):
|
||||
length, disasm = self.disassemble([0x20, 0x97, 0x55])
|
||||
self.assertEqual(3, length)
|
||||
self.assertEqual('JSR $5597', disasm)
|
||||
|
||||
def test_disassembles_21(self):
|
||||
length, disasm = self.disassemble([0x21, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('AND ($44,X)', disasm)
|
||||
|
||||
def test_disassembles_22(self):
|
||||
length, disasm = self.disassemble([0x22])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('???', disasm)
|
||||
|
||||
def test_disassembles_23(self):
|
||||
length, disasm = self.disassemble([0x23])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('???', disasm)
|
||||
|
||||
def test_disassembles_24(self):
|
||||
length, disasm = self.disassemble([0x24, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('BIT $44', disasm)
|
||||
|
||||
def test_disassembles_25(self):
|
||||
length, disasm = self.disassemble([0x25, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('AND $44', disasm)
|
||||
|
||||
def test_disassembles_26(self):
|
||||
length, disasm = self.disassemble([0x26, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('ROL $44', disasm)
|
||||
|
||||
def test_disassembles_27(self):
|
||||
length, disasm = self.disassemble([0x27])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('???', disasm)
|
||||
|
||||
def test_disassembles_28(self):
|
||||
length, disasm = self.disassemble([0x28])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('PLP', disasm)
|
||||
|
||||
def test_disassembles_29(self):
|
||||
length, disasm = self.disassemble([0x29, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('AND #$44', disasm)
|
||||
|
||||
def test_disassembles_30(self):
|
||||
length, disasm = self.disassemble([0x30, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('BMI $0046', disasm)
|
||||
|
||||
def test_disassembles_31(self):
|
||||
length, disasm = self.disassemble([0x31, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('AND ($44),Y', disasm)
|
||||
|
||||
def test_disassembles_32(self):
|
||||
length, disasm = self.disassemble([0x32])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('???', disasm)
|
||||
|
||||
def test_disassembles_33(self):
|
||||
length, disasm = self.disassemble([0x33])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('???', disasm)
|
||||
|
||||
def test_disassembles_34(self):
|
||||
length, disasm = self.disassemble([0x34])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('???', disasm)
|
||||
|
||||
def test_disassembles_35(self):
|
||||
length, disasm = self.disassemble([0x35, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('AND $44,X', disasm)
|
||||
|
||||
def test_disassembles_36(self):
|
||||
length, disasm = self.disassemble([0x36, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('ROL $44,X', disasm)
|
||||
|
||||
def test_disassembles_37(self):
|
||||
length, disasm = self.disassemble([0x37])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('???', disasm)
|
||||
|
||||
def test_disassembles_38(self):
|
||||
length, disasm = self.disassemble([0x38])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('SEC', disasm)
|
||||
|
||||
def test_disassembles_39(self):
|
||||
length, disasm = self.disassemble([0x39, 0x00, 0x44])
|
||||
self.assertEqual(3, length)
|
||||
self.assertEqual('AND $4400,Y', disasm)
|
||||
|
||||
def test_disassembles_40(self):
|
||||
length, disasm = self.disassemble([0x40])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('RTI', disasm)
|
||||
|
||||
def test_disassembles_41(self):
|
||||
length, disasm = self.disassemble([0x41, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('EOR ($44,X)', disasm)
|
||||
|
||||
def test_disassembles_42(self):
|
||||
length, disasm = self.disassemble([0x42])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('???', disasm)
|
||||
|
||||
def test_disassembles_43(self):
|
||||
length, disasm = self.disassemble([0x43])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('???', disasm)
|
||||
|
||||
def test_disassembles_44(self):
|
||||
length, disasm = self.disassemble([0x44])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('???', disasm)
|
||||
|
||||
def test_disassembles_45(self):
|
||||
length, disasm = self.disassemble([0x45, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('EOR $44', disasm)
|
||||
|
||||
def test_disassembles_46(self):
|
||||
length, disasm = self.disassemble([0x46, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('LSR $44', disasm)
|
||||
|
||||
def test_disassembles_47(self):
|
||||
length, disasm = self.disassemble([0x47])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('???', disasm)
|
||||
|
||||
def test_disassembles_48(self):
|
||||
length, disasm = self.disassemble([0x48])
|
||||
self.assertEqual(1, length)
|
||||
self.assertEqual('PHA', disasm)
|
||||
|
||||
def test_disassembles_49(self):
|
||||
length, disasm = self.disassemble([0x49, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('EOR #$44', disasm)
|
||||
|
||||
def test_disassembles_50(self):
|
||||
length, disasm = self.disassemble([0x50, 0x44])
|
||||
self.assertEqual(2, length)
|
||||
self.assertEqual('BVC $0046', disasm)
|
||||
|
||||
# Test Helpers
|
||||
|
||||
def disassemble(self, bytes):
|
||||
mpu = MPU()
|
||||
address_parser = AddressParser()
|
||||
disasm = Disassembler(mpu, address_parser)
|
||||
mpu.memory[0:len(bytes)-1] = bytes
|
||||
return disasm.instruction_at(0)
|
||||
|
||||
def test_suite():
|
||||
return unittest.findTestCases(sys.modules[__name__])
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(defaultTest='test_suite')
|
@ -16,6 +16,14 @@ class AddressParser:
|
||||
self.radix = radix
|
||||
self.labels = labels
|
||||
|
||||
def label_for(self, address, default=None):
|
||||
"""Given an address, return the corresponding label or a default.
|
||||
"""
|
||||
for label, label_address in self.labels.iteritems():
|
||||
if label_address == address:
|
||||
return label
|
||||
return default
|
||||
|
||||
def number(self, num):
|
||||
"""Parse a string containing a label or number into an address.
|
||||
"""
|
||||
|
Loading…
x
Reference in New Issue
Block a user