Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Все ответы.doc
Скачиваний:
18
Добавлен:
09.09.2019
Размер:
3.79 Mб
Скачать

81. Трансляторы с языка ассемблера („ассемблеры“ )

Макроассемблер — транслятор с языка ассемблера, включающий средства определения и использования макрокоманд.

Транслятор с языка ассемблера является компилятором, т.к. язык результирующей программы — машинный код. Язык ассемблер содержит мнемонические коды машинных команд. При этом все команды можно разделить на две группы: обычные команды, которые преобразуются в машинные команды; специальные команды, которые используются компилятором для выполнения задач компиляции (распределение памяти). Каждая команда может быть разделена на три составляющие: поле метки;

код операции; поле операндов.

Компилятор с языка ассемблера обычно предусматривает возможность наличия комментариев, отделяющихся от команд заданным разделителем. Поле метки содержит идентификатор, представляющий собой метку, либо является пустым. Каждый идентификатор метки может встречаться в программе на языке ассемблер только один раз. Метка считается описанной там, где она непосредственно встретилась в программе (предварительное описание меток не требуется). Метка может быть использована для передачи управления на помеченную ею команду. Нередко метка отделяется от остальной части команды специальным разделителем (чаще всего — двоеточием «:»).

Код операции всегда представляет собой строго определенную мнемонику одной из возможных команд процессора или также строго определенную команду самого компилятора. Код операции описывается алфавитными символами входного языка. Чаще всего его длина составляет 3-4, реже — 5 или 6 символов. Поле операндов является пустым, либо представляет собой список из одного, двух, реже — трех операндов. Количество операндов строго определено и зависти от кода операции. Соответственно, каждому из этих вариантов соответствуют безадресные, одноадресные, двухадресные или трехадресные команды. В качестве операндов выступают идентификаторы или константы.

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

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

в компиляторах не выполняется дополнительная идентификация переменных (все переменные языка сохраняют имена, присвоенные им пользователем);

в компиляторах предельно упрощено распределение памяти (работа со статической памятью; если используется динамическая память, то для работы с нею нужно использовать соответствующую библиотеку или функции операционной системы, а за ее распределение отвечает разработчик; разработчик должен организовать передачу данных, монитор памяти процедур и функций, а также отделить данные от кода программы);

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

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