Advertisement
Korotkodul

my_code_3

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