Что такое ассемблер?
Языки ассемблеров
Команды языка ассемблера
Код операции
Псевдооперации
Литералы
Свободный формат команд
Некоторые типичные команды ассемблера для машин с побайтовой организацией
Ассемблеры типа «трансляция — выполнение»
Однопроходный ассемблер
Двухпроходный ассемблер
Символы
Подробная блок-схема прохода
Подробная блок-схема прохода 2
Пример трансляции
Таблицы символов общие замечания
Обработка таблицы
Линейный поиск
Двоичный поиск
Сравнение двоичного и линейного способов поиска
Метод хеширования
Пример хеширования
Скученность
Назначение макрокоманды
Различие между макрокомандами и подпрограммами
Форматы макрокоманды
Ключевой макрос
Макропроцессор

Пример трансляции

Ассемблер не касается того, что по предположению должна делать исходная программа, а занимается лишь производством ее эквивалента в машинном коде. Аналогично, в данном примере интерес представляет только производство эквивалента в машинном коде, а не то, что должна делать программа.

На рис. 5.3 показана очень простая исходная программа, на примере которой можно познакомиться с работой двухпроходного ассемблера. Она фактически ничего не делает, и поэтому легко проследить за ее трансляцией. На первом шаге прохода 1 в счетчик размещения устанавливается значение 0. Читается первый исходный оператор и исследуется его поле операции. START распознается как псевдооперация, и соответствующая директива в таблице псевдоопераций указывает, что дополнительной обработки на проходе 1 не требуется. Затем исследуется поле метки, и в таблицу символов заносится метка NOTHING с текущим значением счетчика размещения, равным нулю. Хотя эквивалент этой метки в машинном коде не требует дополнительного места в памяти, по соглашению длина таких меток равна 1. Эта информация записывается в таблицу символов вместе с отметкой о том, что символ является перемещаемым. Так как START — псевдооперация, не требующая памяти, счетчик размещения остается равным нулю.

Читается следующий оператор, и код операции BALR обнаруживается в таблице кодов операций машины. Метка BEGIN, которой он снабжен, заносится в таблицу символов аналогично предыдущей записи, и счетчик размещения увеличивается на 2, так как BALR имеет длину 2. Длина символа равна длине соответствующей команды. В поле адреса отсутствуют литералы, которые надо обрабатывать, поэтому начинает рассматриваться следующий оператор.

Оператор 3 — снова псевдооперация, которая не должна обрабатываться на проходе 1.
Коды операций операторов 4 и 5 находятся в таблице кодов операций машины и имеют длину 6. При обработке оператора 4 MOVE5 заносится в таблицу символов как перемещаемая величина с адресом 2. Литерал F'5', найденный в поле операндов, помещается в таблицу литералов с длиной 4, так как F означает четырехбайтовое полное слово. Оператор 5 не требует специальных действий на проходе 1, но счетчик размещения увеличивается на его длину, изменяя свое значение с 8 до 14(10)=Е(16).

Операции операторов 6 и 7 находятся в таблице псевдоопераций. Поскольку они влияют на значение счетчика размещения и, кроме того, имеют метки, то должны обрабатываться на проходе 1. Символ DATA1 должен был бы занестись в таблицу символов со значением адреса 14(i0)=E(le), но полные слова нужно выравнивать по границе слова. Ближайшая граница слова—16(10) — Ю(16). Следовательно, это значение приписывается DATA1 наряду с длиной 4. Счетчик размещения увеличивается на 4 и становится равным 20(10)=14(16), и DATA2 заносится в таблицу символов с значением адреса 20(ltf) = 14(1е) и длиной 8. Оба символа помечаются как перемещаемые.

Затем в последнем операторе распознается псевдооперация END, и это говорит о том, что проход 1 должен быть завершен. Просматривается таблица литералов и обнаруживается один литерал длиной в 4 байт, для которого должна быть зарезервирована память.
Он размещается по относительному адресу 28(i0)—1С(1б), и таким образом завершается проход I.   

Первой на проходе 2 обрабатывается псевдооперация START. Через таблицу глобальных символов редактору связей пересылается информация о том, что метка NOTHING, связанная с данной операцией, является именем программы. Код для BALR выбирается из таблицы кодов операций машины.

Для команд типа RR значения регистров фактически подставляются в поле адреса команды. Следовательно, первая сгенерированная машинная команда имеет вид (в шестнадцатеричной записи) D540, где D5 обозначает операцию BALR, а 4 и 0 обозначают адреса.

В результате обработки оператора 3 поступает информация о том, что регистр 4 будет использоваться в качестве базового регистра, и что его содержимое будет равно 2. Никакого машинного кода не генерируется, так как в поле операнда расположен код псевдооперации.
Для операции MVC, содержащейся в операторе 4, генерируется машинный код D2. Так как это операция типа SS, адреса должны формироваться как сумма смещения и содержимого базового регистра. Из таблицы символов и таблицы литералов определется, что длина полей, используемых в команде в качестве операндов, равна 4, а их адреса равны соответственно 10 и 1С (в шестнадцатеричном виде). Единственный доступный базовый регистр — регистр 4 с содержимым 2. Так как в команде не указано индексного регистра, смещения равны соответственно 10—2 = Е и 1С—2=1 А. Таким образом, полностью собранная команда имеет вид D203400E401A. (См. разд. 4.4.8 для выяснения смысла различных байтов в формате команд SS, а также рис. 4.7.) Оператор 5 строится аналогичным образом.

Операторы 6 и 7 обработаны на проходе 1 и не требуют никаких действий на проходе 2. Оператор 8 содержит псевдооперацию END, но перед завершением прохода 2 должны быть сгенерированы значения присутствующих в программе литералов. В программе только один литерал — константа F'5'. Так как она представляет собой полное слово, 00000005(16) помещается в приписанную ей на первом проходе ячейку 1С.

Машинное представление этой.«программы» показано на рис. 5.5. Для наглядности в него включены также границы байтов и команд, мнемонические коды операций и символические и относительные адреса. Ясно, что эта программа не завершится правильно, так как если бы она выполнялась, то после исполнения второй команды процессор проинтерпретировал бы 00 в относительной ячейке Е как следующую операцию.

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

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

Hosted by uCoz