|
4 | 4 |
|
5 | 5 | from . import opcodes
|
6 | 6 |
|
| 7 | +TEXT, DATA, BSS = 'text', 'data', 'bss' |
| 8 | + |
7 | 9 | class Assembler:
|
| 10 | + |
8 | 11 | def __init__(self):
|
9 | 12 | self.symbols = {}
|
10 |
| - self.code = [] |
11 |
| - self.addr = 0 |
| 13 | + self.sections = dict(text=[], data=[], bss=0) |
| 14 | + self.offsets = dict(text=0, data=0, bss=0) |
| 15 | + self.section = TEXT |
12 | 16 |
|
13 | 17 | def parse_line(self, line):
|
14 | 18 | """
|
@@ -48,18 +52,59 @@ def parse(self, lines):
|
48 | 52 | return [p for p in parsed if p is not None]
|
49 | 53 |
|
50 | 54 |
|
| 55 | + def append_section(self, value, expected_section=None): |
| 56 | + s = self.section |
| 57 | + if expected_section is not None and s is not expected_section: |
| 58 | + raise TypeError('only allowed in %s section' % expected_section) |
| 59 | + if s is TEXT or s is DATA: |
| 60 | + self.sections[s].append(value) |
| 61 | + self.offsets[s] += 1 |
| 62 | + elif s is BSS: |
| 63 | + self.sections[s] += value # just increase BSS size by value |
| 64 | + |
| 65 | + def dump(self): |
| 66 | + print("Symbols:") |
| 67 | + for label, section_offset in sorted(self.symbols.items()): |
| 68 | + print(label, section_offset) |
| 69 | + print("%s section:" % TEXT) |
| 70 | + for t in self.sections[TEXT]: |
| 71 | + print(hex(t)) |
| 72 | + print("%s section:" % DATA) |
| 73 | + for d in self.sections[DATA]: |
| 74 | + print(d) |
| 75 | + print("%s section:" % BSS) |
| 76 | + print("size: %d" % self.sections[BSS]) |
| 77 | + |
| 78 | + def d_text(self): |
| 79 | + self.section = TEXT |
| 80 | + |
| 81 | + def d_data(self): |
| 82 | + self.section = DATA |
| 83 | + |
| 84 | + def d_bss(self): |
| 85 | + self.section = BSS |
| 86 | + |
51 | 87 | def assemble(self, lines):
|
52 | 88 | for label, opcode, args in self.parse(lines):
|
53 | 89 | if label is not None:
|
54 | 90 | if label in self.symbols:
|
55 | 91 | raise Exception('label %s is already defined.' % label)
|
56 |
| - self.symbols[label] = self.addr |
| 92 | + self.symbols[label] = (self.section, self.offsets[self.section]) |
57 | 93 | if opcode is not None:
|
58 |
| - func = getattr(opcodes, 'i_' + opcode, None) |
59 |
| - if func is None: |
60 |
| - raise Exception('Unknown opcode: %s' % opcode) |
61 |
| - instruction = func(*args) |
62 |
| - self.code.append(instruction) |
63 |
| - self.addr += 1 |
64 |
| - return self.symbols, self.code |
| 94 | + if opcode[0] == '.': |
| 95 | + # assembler directive |
| 96 | + func = getattr(self, 'd_' + opcode[1:]) |
| 97 | + if func is not None: |
| 98 | + result = func(*args) |
| 99 | + if result is not None: |
| 100 | + self.append_section(result) |
| 101 | + continue |
| 102 | + else: |
| 103 | + # machine instruction |
| 104 | + func = getattr(opcodes, 'i_' + opcode, None) |
| 105 | + if func is not None: |
| 106 | + instruction = func(*args) |
| 107 | + self.append_section(instruction, TEXT) |
| 108 | + continue |
| 109 | + raise Exception('Unknown opcode or directive: %s' % opcode) |
65 | 110 |
|
0 commit comments