Advertisement
Korotkodul

my_code_8

Apr 4th, 2025 (edited)
161
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.13 KB | None | 0 0
  1. import pyparsing as pp
  2.  
  3. # Улучшенные определения элементов
  4. identifier = pp.Word(pp.alphas, pp.alphanums + "_")
  5. mnemonic = pp.oneOf("mov add sub halt", caseless=True)  # Список команд
  6. command_name = mnemonic("command")
  7.  
  8. # Числа: #10 или 10 (целые)
  9. number = pp.Combine(pp.Optional('#') + pp.Word(pp.nums))
  10. # Регистры: r0, r1, ..., r15
  11. register = pp.Combine(pp.CaselessLiteral('r') + pp.Word(pp.nums, max=2))
  12. argument = number | register | identifier
  13. arguments = pp.Group(pp.delimitedList(argument, delim=pp.Suppress(',')))("args")
  14.  
  15. label = (identifier + pp.Suppress(":"))("label")
  16. comment = (pp.Suppress(';') + pp.restOfLine.setParseAction(lambda t: t[0].strip()))("comment")
  17.  
  18. # Основное правило
  19. rule = (
  20.     pp.Optional(label, default='')
  21.     + pp.Optional(command_name, default='')
  22.     + pp.Optional(arguments, default=[])
  23.     + pp.Optional(comment, default='')
  24. )
  25.  
  26. debug_mode = False
  27.  
  28. def parse_line(s):
  29.     s = s.lower().strip()
  30.     if s[0] == '.':
  31.         s = s.replace(" ", "")
  32.         return {'label': '', 'command_name': 'start_from_address', 'arguments': [ s[2:] ], 'comment': ''}
  33.     parsed = rule.parseString(s, parseAll=True)
  34.     args = []
  35.     if len(parsed.args) != 0:
  36.         args = parsed.args.asList()
  37.     comment = ''
  38.     if parsed.comment  != '':
  39.         comment = parsed.comment[0]
  40.     label = ''
  41.     if parsed.label != '':
  42.         label = parsed.label[0]
  43.     result = {
  44.         'label': label,
  45.         'command_name': parsed.command if 'command' in parsed else '',
  46.         'arguments': args,
  47.         'comment': comment
  48.     }
  49.     return result
  50.  
  51. assembler_code = []
  52. blocks = []
  53. dict_machine_code = {'start': '', 'data': []}
  54.  
  55. filename = 'asm_code.txt'
  56. with open(filename, 'r', encoding='utf-8') as file:
  57.     for line in file:
  58.         line = line.lower().strip()
  59.         assembler_code.append(parse_line(line))
  60.  
  61. print("assembler_code:", assembler_code)
  62.  
  63. def to3bit(x):
  64.     res = str(bin(int(x))[2:])
  65.     while len(res) < 3:
  66.         res = '0' + res
  67.     return res
  68.  
  69. def to_four_digit_hex_number(x):
  70.     res = str(hex(int(x)))[2:]
  71.     while len(res) < 4:
  72.         res = '0' + res
  73.     return res
  74.  
  75. #Пока без label (лейблы могут быть, но они никак не обрабатываются и не записываются в машинный код)
  76.  
  77. command_description = {
  78.     # Однобайтовые команды
  79.     'halt': {
  80.         'opcode': '0' * 16,  #Код операции MOV (в hex)
  81.         'args': []
  82.     },
  83.     # Двухадресные команды
  84.     'mov': {
  85.         'opcode': '0001',
  86.         'args': ['mr', 'mr']  #ss = mr, dd = mr - mode, register
  87.     },
  88.     'add': {
  89.         'opcode': '0110',
  90.         'args': ['mr', 'mr']
  91.     },
  92. }
  93.  
  94. def get_command_by_name(name):
  95.     return command_description[name]
  96.  
  97. def to16bit(x):
  98.     res = bin(x)[2:]
  99.     while len(res) < 16:
  100.         res = '0' + res
  101.     return res
  102.  
  103. def from8to10(s):
  104.     x = 0
  105.     s = s[::-1]
  106.     for i in range(len(s)):
  107.         x += int(s[i]) * 8**i
  108.     return x
  109.  
  110. def from8to16bit(s):
  111.     return  to16bit(from8to10(s))
  112.  
  113. def decode_mr_arg(arg):
  114.     """
  115.    :param arg:
  116.    :return:
  117.    только для ss и dd: mode, register
  118.    """
  119.     additional_word = ''
  120.     mode = ''
  121.     register = ''
  122.     if arg[0] == 'r': # R3
  123.         mode = '000'
  124.         register = to3bit(arg[1])
  125.     elif  arg[0] == '(' and arg[-1] == ')': # (R3)
  126.         mode = '001'
  127.         register = to3bit(arg[2])
  128.     elif arg[0] == '(' and arg[-1] == '+': # (R3)+
  129.         mode = '010'
  130.         register = to3bit(arg[2])
  131.     elif arg[0] == '@' and arg[-1] == '+': # @(R3)+
  132.         mode = '011'
  133.         register = to3bit(arg[3])
  134.     elif arg[0] == '-':  # -(R3)
  135.         mode = '100'
  136.         register = to3bit(arg[3])
  137.     elif arg[0] == '@' and arg[1] == '-': # @-(R3)
  138.         mode = '101'
  139.         register = to3bit(arg[4])
  140.     elif arg[0] == '@' and arg[-1] == ')': # @2(R3)
  141.         mode = '111'
  142.         register = to3bit(arg[-2])
  143.         additional_word = from8to16bit(arg[1:-4])
  144.     elif arg[0] in '01234567' and arg[-1] == ')': # 2(R3)
  145.         mode = '110'
  146.         register = to3bit(arg[-2])
  147.         additional_word = from8to16bit(arg[:-4])
  148.     elif arg[0] == '#': # #3
  149.         mode = '010'
  150.         register = '111'
  151.         additional_word = from8to16bit(arg[1:])
  152.     elif arg[0] == '@' and arg[1] == '#': # @#100
  153.         mode = '011'
  154.         register = '111'
  155.         additional_word = from8to16bit(arg[2:])
  156.     elif arg[0] == '@' and arg[1] != '#': # @100
  157.         mode = '111'
  158.         register = '111'
  159.         additional_word = from8to16bit(arg[1:])
  160.     elif arg[0] in '01234567': # 100
  161.         mode = '110'
  162.         register = '111'
  163.         additional_word = from8to16bit(arg)
  164.     code_arg = mode + register
  165.     return code_arg, additional_word
  166.  
  167. #на случай # у нас есть переменные additional...
  168. def cmd_to_raw_machine_code(command, start_address=None):
  169.     """
  170.    Перевод {'label': 'label1', 'command_name': 'mov', 'arguments': ['#3', 'r1'], 'comment': 'comment2'}
  171.     в ['0001010111000001', '0003'], только вмсто 0003 тавим 16 бит которые соответствуют 0003 или как? в принципеможно просто
  172.     0003 оставить и потом просто на длину смотртеь? было бы прощ
  173.    """
  174.  
  175.     """
  176.        Перевод ['mov', '#2', 'r0'] в [0o012700, 2]
  177.        """
  178.     # по имени команды записываешь в результирующее слово опкод команды
  179.     print("command:", command)
  180.     command_name = command['command_name']
  181.     if command_name == 'start_from_address':
  182.         return [command['arguments'][0], 'num_of_bytes_in_file']
  183.  
  184.     cmd = get_command_by_name(command_name)
  185.     """return {
  186.        'opcode': '1000',
  187.        'args': ['ss', 'dd'],  # source, destination
  188.    }"""
  189.     parse_args = command['arguments'] #['#2', 'r1']
  190.     command_code = cmd['opcode']
  191.     additional_words = []
  192.     for arg, parse_arg in zip(cmd['args'], parse_args):
  193.         # arg='mr', parse_arg='#2'
  194.         code_arg = ''
  195.         additional_word = ''
  196.         match arg:
  197.             case 'mr':
  198.                 code_arg, additional_word = decode_mr_arg(parse_arg)
  199.                 command_code += code_arg
  200.                 if additional_word != '':
  201.                     additional_words.append(additional_word)
  202.             # code_arg = '010111'  27
  203.             # additional_word = '...'   2  вот тут может быть использование лейбла и его посчитаем во второй проход
  204.             # code_arg добавляем в кодировку текущей команды
  205.             # если дополнительное слово есть, его присоедняем к списку слов
  206.     res = [command_code]
  207.     for w in additional_words:
  208.         res.append(w)
  209.     print("return:", res)
  210.     return res
  211.  
  212. def asm_to_binary_code(asm_code):
  213.     res = []
  214.     for line in asm_code:
  215.         bin_numbers = cmd_to_raw_machine_code(line)
  216.         for bin_num in bin_numbers:
  217.             res.append(bin_num)
  218.     return res
  219.  
  220. binary_code = asm_to_binary_code(assembler_code)
  221. print("binary_code:", binary_code)
  222.  
  223. def from2to10(s):
  224.     s = s[::-1]
  225.     x = 0
  226.     for i in range(len(s)):
  227.         x += int(s[i]) * 2**i
  228.     return x
  229.  
  230. def bits_to_bytes(bin_command_code):
  231.     piece1 = bin_command_code[:4]
  232.     piece2 = bin_command_code[4:8]
  233.     piece3 = bin_command_code[8:12]
  234.     piece4 = bin_command_code[12:]
  235.     # print("pieces", piece1, piece2, piece3, piece4)
  236.     num1 = hex(int(piece1, 2))[2:] + hex(int(piece2, 2))[2:]
  237.     num2 = hex(int(piece3, 2))[2:] + hex(int(piece4, 2))[2:]
  238.     machine_command = [num2, num1]
  239.     return machine_command
  240.  
  241.  
  242. machine_code = []
  243. for line in binary_code:
  244.     if len(line) != 16:
  245.         machine_code.append(line)
  246.         continue
  247.     byte1, byte2 = bits_to_bytes(line)
  248.     machine_code.append(byte1)
  249.     machine_code.append(byte2)
  250. print("machine_code:", machine_code)
  251.  
  252.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement