Расширение синтаксиса ассемблера

Comment are off

Мы уже говорили что некоторые тонкости системы команд «Эверест» спрятаны за ассемблерными макросами. Пока не готов компилятор Си, нам приходится много писать на ассемблере и приходится прилагать много усилий для реализации сложных алгоритмов. Одной из проблем является необходимость помнить за что отвечает каждый из использованных регистров. Поэтому было принято решение о введении алиасов для регистров.

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

item_counter

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

Для решения этой проблемы мы добавили возможность именовать регистры с помощью новой директивы ASSIGN.

assign r1 alias_for_structure ; Назначение имени регистру R1

Таким образом далее в тексте программы любое упоминание сочетания alias_for_structure автоматически заменяется на регистр r1.

Теперь берём на себя обязанности компилятора и вручную генерируем ассемблерный код для вышеприведённого примера программы:
sample_2_code

Строка с комментарием «просто тест» и есть просто тест, демонстрирующая возможности адресации. В случае генерации кода компилятором она бы не появилась в этом коде. Мы добавили её чтобы показать возможности нашего ассемблера. Заглянем в дизассемблированный дамп чтобы увидеть машинный код, сгенерированный из нашего примера:

sample_2_disasm

Теперь понятно, для чего мы добавили в пример лишнюю строку с чтением поля data_ptr структуры list_item — при нулевом смещении (первое поле структуры) ассемблер использует более короткую форму инструкции, что продемонстрировано на последней картинке.

Также мы обнаружили и исправили несколько небольших ошибок в ассемблере.

Наконец, мы обновили версию макроассемблера на нашем сайте, поместив в один архив версию для Windows и версию для Linux — обе версии собраны из одного и того же исходного кода. Чтобы получить исполняемые версии для Linux, вам потребуется с помощью следующей инструкции распаковать вложенный архив с исполняемым кодом для Linux:

tar xf linux_bin.tar

Оставить комментарий