Встроенный ассемблер

Встроенный ассемблер Logisim-evolution предназначен для трансляции исходного текста программ в исполняемый машинный код (байт-код) целевого процессора. Редактор поддерживает автоматическую подсветку синтаксиса и динамическое обнаружение ошибок.

Примечание архитектора: Хотя внутренняя структура компилятора проектировалась с возможностью генерации стандартных файлов формата ELF, на данный момент эта функция находится в стадии разработки — генерация машинного кода осуществляется напрямую в память имитационной модели.

Интерфейс графического редактора

При запуске ассемблера открывается рабочее окно, состоящее из трёх основных областей:

Графический интерфейс ассемблера

  1. Панель инструментов — верхняя горизонтальная панель со значками быстрого доступа;
  2. Панель нумерации строк — левая вертикальная полоса, на которой также отображаются маркеры ошибок;
  3. Область редактирования — текстовое поле для написания и разбора исходного кода.

Функции панели инструментов

Иконки на панели предоставляют быстрый доступ к командам (многие из них продублированы горячими клавишами):

Открыть — Загрузить файл: открывает исходный код из внешнего файла на диске. Горячие клавиши: Ctrl-L.

Сохранить — Сохранить файл: перезаписывает текущий открытый файл. Горячие клавиши: Ctrl-S.

Сохранить как — Сохранить как…: открывает диалоговое окно для сохранения файла под новым именем.

Компилировать — Ассемблировать: выполняет синтаксический анализ и трансляцию кода без загрузки. Горячие клавиши: Alt-A.

Предыдущая ошибка — Предыдущая ошибка: перемещает курсор к ближайшей ошибке выше по тексту. Горячие клавиши: Ctrl-P.

Следующая ошибка — Следующая ошибка: перемещает курсор к ближайшей ошибке ниже по тексту. Горячие клавиши: Ctrl-N.

Запуск — Собрать и загрузить: транслирует код и, при отсутствии ошибок, автоматически прошивает полученный байт-код в память имитационной модели SoC. Горячие клавиши: Alt-R.

Справка — Справка: открывает текущую страницу документации.

Индикатор изменений: Справа от кнопок выводится текущая позиция курсора (строка/колонка) и общее число строк. Если этот счётчик подсвечивается жёлтым цветом, это сигнализирует о наличии несохранённых изменений в коде.

Диагностика ошибок в тексте

Строки с некорректным кодом подчёркиваются в редакторе тонкой красной линией, а на левой панели появляется соответствующий значок. При наведении указателя мыши на подчёркнутый фрагмент или на значок ошибки всплывает текстовое окно с её подробным описанием.

Важные ограничения парсера:

Математические вычисления и выражения

Ассемблер позволяет использовать математические выражения для динамического расчёта адресов и констант. Выражения разделяются на два типа:

  1. Относительно счётчика команд (PC): расчёт смещения ведётся от текущей исполняемой инструкции с обязательным использованием зарезервированного ключевого слова pc (например: pc+8, pc-0x40, mylabel-pc);
  2. Абсолютные вычисления: рассчитывают константное статическое значение с использованием предопределённых глобальных меток и констант.

Поддерживаемые арифметические операторы

Ограничение синтаксиса: Круглые скобки для явного задания приоритета в текущей версии ассемблера не поддерживаются.

КРИТИЧЕСКИ ВАЖНОЕ ПРАВИЛО:

Вычисления выполняются строго последовательно слева направо, стандартный математический приоритет операторов полностью отсутствует!


Использование макросов

Макросы позволяют автоматизировать вставку повторяющихся блоков инструкций. Шаблон объявления макроса имеет вид:

.macro <имя_макроса> <количество_аргументов>
    [Тело макроса: инструкции и локальные метки]
.endm

Параметризация: Внутри тела макроса обращение к переданным аргументам выполняется по их порядковому номеру через символ @ (например: @1 — первый параметр, @2 — второй и т. д.).

Локальная область видимости: Все метки, объявленные внутри тела макроса, изолированы (локальны) — к ним невозможно обратиться из основного кода программы. Сам макрос при этом может свободно ссылаться на любые внешние глобальные метки.

Вложенность: Допускается вызов одного макроса из тела другого. Однако рекурсия (вызов макросом самого себя) и циклические вызовы (взаимный вызов двух макросов друг другом) строго запрещены.


Директивы ассемблера

Объявление меток

Метки служат для именования контрольных точек и адресов переходов. Они декларируются с двоеточием на конце: <имя_метки>:. Имя метки обязано начинаться с латинской буквы и может состоять из символов латиницы, цифр и знака подчёркивания.

Объявление именованных констант (.equ)

Константы связывают текстовое имя со статическим значением. Синтаксис: .equ <имя> <значение_или_выражение>. Имя также должно начинаться строго с буквы.

Разделение на секции (.section)

Директива позволяет разбить исходный образ на функциональные сегменты: .section <имя_секции>. Поддерживаются четыре стандартных системных сегмента, для которых ключевое слово .section можно опускать:

Комментарии (#)

Любой текст, расположенный в строке после символа решётки (#), считается комментарием и отбрасывается компилятором. Многострочные комментарии требуют установки символа # в начале каждой строки.

Строковые литералы

Для размещения строк в памяти используются директивы .string, .ascii или .asciz, после которых текст указывается в двойных кавычках: "текст". Строка может содержать стандартные управляющие escape-последовательности:

Важное отличие: Директивы .string и .asciz в отличие от .ascii автоматически добавляют в конец строки скрытый нулевой байт (\0), сигнализирующий о завершении строки.

Управление адресацией памяти (.org)

По умолчанию сборка проекта начинается с нулевого адреса (0x00000000). Изменить текущий указатель адреса размещения последующих инструкций или данных можно директивой .org <32-битный_адрес>.

Внимание: Ассемблер контролирует пересечения адресов только на границах разных секций. Если внутри одного сегмента директива .org возвращает указатель назад на уже заполненную область, старые данные будут перезаписаны новыми без вывода предупреждений.

Размещение констант в памяти

Для заполнения памяти фиксированными значениями используются перечисленные ниже директивы. При работе с многобайтными величинами упаковка данных всегда выполняется по стандарту little-endian (младший байт пишется по меньшему адресу):

  1. Побайтово: .byte выражение1[, выражение2, ...] — запись последовательности 8-битных данных;
  2. По словесно (16 бит): .half, .2byte или .short значение1[, значение2, ...] — последовательность 16-битных слов;
  3. По двойному слову (32 бита): .word, .4byte или .long значение1[, значение2, ...] — последовательность 32-битных значений;
  4. По четвёрному слову (64 бита): .dword, .8byte или .quad значение1[, значение2, ...] — последовательность 64-битных значений.