Метки

Последнее обновление: 01.03.2024

Метки позволяют назначить имя определенной строке с инструкцией программы и в дальнейшем ссылаться на эту строку. Также метки позволяют определять переменные в программе и затем чрез метку можно ссылаться на переменную. Обычно метка представляет собой произвольный идентификатор, за которым следует двоеточие:

label: инструкция

Например:

_start:
    mov r0, 1
    mov r1, 2 
set_r2:  mov r2, 3

Здесь используются две метки: "_start" и "_set_r2". Метка "_start" фактически представляет адрес инструкции mov r0, 1, тогда как метка "set_r2" - mov r2, 3

Общий принцип обработки меток заключается в том, что определяется некоторая структура данных, которая содержит название метки и адрес, который она представляет. В Python для этой цели можно использовать словарь.

Проблема с обработками меток может заключаться в том, что нам надо решить должны ли метки быть уникальными или нет. Обычно имена меток уникальны, и нельзя определить двух меток с одним именем или переопределить.

Итак, пусть у нас есть файл "hello.s" со следующим кодом:

// парсинг меток на ассемблере
_start:                // метка _start
    mov r0, 1
    mov r1, 2 
set_r2:  mov r2, 3     // метка set_r2

Для парсинга меток определим следующую программу на языке Python:

instructions = []       # иструкции, разбитые по токенам
sym_tab = {}      # таблица символов
addr = 0        # адрес инструкции

# считываем файл hello.s в список инструкций
with open("hello.s", "r", encoding="utf8") as source:
    lines = source.readlines()
    # обрабатываем строки из файла
    for i in range(0,len(lines)):
        lines[i] = lines[i].split("//")[0] \
                    .replace(",", " ")  \
                    .strip().rstrip("\n") \
                    .lower()
        while "  " in lines[i]:             # заменяем несколько пробелов одним
            lines[i] = lines[i].replace("  ", " ")  
        if(lines[i]) == "": continue        # если получилась пустая строка, переходим к следующей строке

        tokens = lines[i].split(" ")      # разбиваем инструкцию на токены
    
        # если токен заканчивается на двоеточие, то это метка
        if(tokens[0][-1]==":"):
            label = tokens[0][:-1]
            if(label in sym_tab):       # проверяем наличие метки
                print("Метка", label, "уже существует")
                break
            sym_tab[label] = addr    # добавляем метку в таблицу символов
            if(len(tokens)==1): continue      # если инструкция на следующей строке, переходим к ней
            else: tokens = tokens[1:]         # получаем токены инструкции
            
        instructions.append(tokens)         # добавляем инструкцию в список instructions
        print("adr:",addr, tokens)      # для наглядности логгируем инструкцию и адрес
        addr = addr + 1                 # увеличиваем указатель инструкций

print(sym_tab)  # выводим таблицу символов

Здесь вначала определяем список для хранения инструкций instructions. Для хранения меток определяем словарь sym_tab. А для учета адреса инструкции - переменную addr:

instructions = []       # иструкции, разбитые по токенам
sym_tab = {}      # таблица символов
addr = 0        # адрес инструкции

После базовой обработки файла разбиваем строку на токены и проверяем первый. Если он завершается на двоеточие, то он представляет метку:

tokens = lines[i].split(" ") 
if(tokens[0][-1]==":"):

В этом случае получаем метку и проверяем ее наличие в словаре:

label = tokens[0][:-1]
if(label in sym_tab):       # проверяем наличие метки
    print("Метка", label, "уже существует")
    break

Если метка уже есть, завершаем обработку. Иначе добавляем ее в словарь sym_tab:

sym_tab[label] = addr

Если инструкция размещена на последующей строке, то переходим к этой строке. Если инструкция идет сразу после метки на той же строке, то удаляем из списка токенов метку:

if(len(tokens)==1): continue      # если инструкция на следующей строке, переходим к ней
else: tokens = tokens[1:]         # получаем токены инструкции

После обработки метки добавляем токены (из которых исключена метка) в список инструкций instructions и увеличиваем адрес инструкций addr

instructions.append(tokens)         # добавляем инструкцию в список instructions
print("adr:",addr, tokens)      # для наглядности логгируем инструкцию и адрес
addr = addr + 1                 # увеличиваем указатель инструкций

Таким образом, в словаре sym_tab окажутся всем метки с адресами инструкций, а в списке instructions - инструкции, разбитые по токена.

Запустим программу на примере выше приведенного файла "hello.s" и получим следующий вывод:

adr: 0 ["mov", "r0", "1"]
adr: 1 ["mov", "r1", "2"]
adr: 2 ["mov", "r2", "3"]
{"_start": 0, "set_r2": 2}
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850