Advertisement
    SHARE
    TWEET
    Korotkodul

    my_code_2

    Apr 3rd, 2025
    381
    0
    Never
    Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
    Python 8.78 KB | None | 0 0
    1. import pyparsing as pp
    2. import re
    3. import struct
    4. from typing import List, Dict, Union
    5. class PDP11Assembler:
    6. def __init__(self):
    7. # Инициализация парсера pyparsing (как в вашем коде)
    8. self.command_name = pp.Word(pp.alphas)
    9. self.argument_name = pp.Word(pp.printables, exclude_chars=';,')
    10. self.arguments = pp.Optional(self.argument_name) + pp.ZeroOrMore(pp.Suppress(',') + self.argument_name)
    11. self.label = pp.Word(pp.alphas) + pp.Optional(pp.Suppress(' ')) + pp.Suppress(":")
    12. self.comment = pp.Suppress(';') + pp.Optional(pp.Suppress(' ')) + pp.restOfLine()
    13. self.rule = pp.Optional(self.label) + pp.Optional(self.command_name) + pp.Optional(
    14. self.arguments) + pp.Optional(self.comment)
    15. # Таблица команд (расширенная версия)
    16. self.command_table = {
    17. 'halt': {'opcode': 0o000000, 'args': [], 'handler': self._handle_no_args},
    18. 'mov': {'opcode': 0o010000, 'args': ['ss', 'dd'], 'handler': self._handle_ss_dd},
    19. 'add': {'opcode': 0o060000, 'args': ['ss', 'dd'], 'handler': self._handle_ss_dd},
    20. 'sub': {'opcode': 0o160000, 'args': ['ss', 'dd'], 'handler': self._handle_ss_dd},
    21. 'cmp': {'opcode': 0o020000, 'args': ['ss', 'dd'], 'handler': self._handle_ss_dd},
    22. 'br': {'opcode': 0o000400, 'args': ['xx'], 'handler': self._handle_branch},
    23. 'bne': {'opcode': 0o001000, 'args': ['xx'], 'handler': self._handle_branch},
    24. }
    25. self.labels = {}
    26. self.current_address = 0o1000
    27. self.output_blocks = []
    28. def parse_line(self, line: str) -> List[str]:
    29. """Аналог вашей функции parse с улучшениями"""
    30. line = line.strip()
    31. if not line:
    32. return []
    33. if line.startswith('.'):
    34. if line.startswith('.='):
    35. return ['origin', line[2:].strip()]
    36. return []
    37. try:
    38. return self.rule.parseString(line).asList()
    39. except pp.ParseException:
    40. return []
    41. def _handle_no_args(self, cmd: Dict, args: List[str], words: List[Union[int, str]]):
    42. """Обработка команд без аргументов"""
    43. words.append(cmd['opcode'])
    44. def _handle_branch(self, cmd: Dict, args: List[str], words: List[Union[int, str]]):
    45. """Обработка команд ветвления"""
    46. words.append(cmd['opcode'])
    47. words.append(args[0]) # Сохраняем метку для разрешения позже
    48. def _handle_ss_dd(self, cmd: Dict, args: List[str], words: List[Union[int, str]]):
    49. """Обработка двухоперандных команд"""
    50. src = self._parse_operand(args[0])
    51. dst = self._parse_operand(args[1])
    52. instruction = cmd['opcode'] | (src['mode'] << 6) | (src['reg'] << 3) | dst['mode'] | dst['reg']
    53. words.append(instruction)
    54. if src['mode'] == 0o27: # Немедленная адресация
    55. words.append(src['value'])
    56. def _parse_operand(self, op: str) -> Dict[str, Union[int, str]]:
    57. """Улучшенный парсер операндов"""
    58. if not op:
    59. return {'mode': 0, 'reg': 0, 'value': 0}
    60. # Регистровая адресация (R0-R7)
    61. if re.match(r'^[rR][0-7]$', op):
    62. return {'mode': 0, 'reg': int(op[1]), 'value': 0}
    63. # Немедленная адресация (#n)
    64. if op.startswith('#'):
    65. return {'mode': 0o27, 'reg': 0, 'value': int(op[1:])}
    66. return {'mode': 0, 'reg': 0, 'value': 0}
    67. def cmd_to_raw_machine_code(self, parsed: List[str]) -> List[Union[int, str]]:
    68. """Аналог вашей функции, но с улучшенной структурой"""
    69. if not parsed:
    70. return []
    71. if isinstance(parsed[0], list) and len(parsed[0]) == 2 and parsed[0][1] == ':':
    72. # Обработка метки
    73. label = parsed[0][0]
    74. self.labels[label] = self.current_address
    75. parsed = parsed[1:]
    76. if not parsed:
    77. return []
    78. if parsed[0] == 'origin':
    79. self.current_address = int(parsed[1], 8)
    80. return []
    81. cmd_name = parsed[0].lower()
    82. if cmd_name not in self.command_table:
    83. return []
    84. cmd = self.command_table[cmd_name]
    85. args = parsed[1:]
    86. if len(args) != len(cmd['args']):
    87. return []
    88. words = []
    89. cmd['handler'](cmd, args, words)
    90. return words
    91. def first_pass(self, lines: List[str]):
    92. """Первый проход: сбор меток"""
    93. self.current_address = 0o1000
    94. for line in lines:
    95. parsed = self.parse_line(line)
    96. if not parsed:
    97. continue
    98. if parsed[0] == 'origin':
    99. self.current_address = int(parsed[1], 8)
    100. continue
    101. if isinstance(parsed[0], list) and len(parsed[0]) == 2 and parsed[0][1] == ':':
    102. label = parsed[0][0]
    103. self.labels[label] = self.current_address
    104. parsed = parsed[1:]
    105. if not parsed:
    106. continue
    107. cmd_name = parsed[0].lower()
    108. if cmd_name in self.command_table:
    109. cmd = self.command_table[cmd_name]
    110. self.current_address += 2 # Основное слово команды
    111. # Учет дополнительных слов
    112. for arg in parsed[1:]:
    113. if arg.startswith('#'):
    114. self.current_address += 2
    115. def second_pass(self, lines: List[str]):
    116. """Второй проход: генерация машинного кода"""
    117. self.current_address = 0o1000
    118. current_block = {'start': 0o1000, 'data': []}
    119. for line in lines:
    120. parsed = self.parse_line(line)
    121. if not parsed:
    122. continue
    123. if parsed[0] == 'origin':
    124. if current_block['data']:
    125. self.output_blocks.append(current_block)
    126. addr = int(parsed[1], 8)
    127. current_block = {'start': addr, 'data': []}
    128. self.current_address = addr
    129. continue
    130. if isinstance(parsed[0], list) and len(parsed[0]) == 2 and parsed[0][1] == ':':
    131. parsed = parsed[1:]
    132. if not parsed:
    133. continue
    134. words = self.cmd_to_raw_machine_code(parsed)
    135. for item in words:
    136. if isinstance(item, str): # Метка для ветвления
    137. offset = (self.labels[item] - self.current_address - 2) // 2
    138. current_block['data'][-1] |= (offset & 0o377)
    139. else:
    140. current_block['data'].append(item)
    141. self.current_address += 2
    142. if current_block['data']:
    143. self.output_blocks.append(current_block)
    144. def write_s_record_format(self, filename: str):
    145. """Запись результата в требуемом формате"""
    146. if not self.output_blocks:
    147. return
    148. block = self.output_blocks[0]
    149. data_bytes = bytearray()
    150. for word in block['data']:
    151. # Правильный порядок байтов (как в вашем примере)
    152. data_bytes.append(word & 0xFF)
    153. data_bytes.append((word >> 8) & 0xFF)
    154. with open(filename, 'w') as f:
    155. # Первая строка: адрес и размер
    156. f.write(f"0200 {len(data_bytes):04x}\n")
    157. # Байты машинного кода
    158. for byte in data_bytes:
    159. f.write(f"{byte:02x}\n")
    160. def assemble(self, input_filename: str, output_filename: str):
    161. """Основной метод ассемблирования"""
    162. with open(input_filename, 'r') as f:
    163. lines = f.readlines()
    164. # Два прохода
    165. self.first_pass(lines)
    166. self.second_pass(lines)
    167. # Запись результата
    168. self.write_s_record_format(output_filename)
    169. # Пример использования
    170. if __name__ == "__main__":
    171. assembler = PDP11Assembler()
    172. test_code = """
    173. .=1000
    174. mov #2, r0
    175. mov #3, r1
    176. add r0, r1
    177. halt
    178. """
    179. with open("test.asm", "w") as f:
    180. f.write(test_code)
    181. assembler.assemble("test.asm", "output.txt")
    182. print("Ассемблирование завершено. Результат в output.txt")
    Advertisement
    Add Comment
    Please, Sign In to add comment
    Advertisement
    Public Pastes
    Advertisement
    We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
    Not a member of Pastebin yet?
    Sign Up, it unlocks many cool features!

    AltStyle によって変換されたページ (->オリジナル) /