|
Простейший ассемблер делает два прохода по входному потоку (в данном случае проход — разовое считывание входного файла). При первом проходе находятся все идентификаторы, обозначающие ячейки памяти, и размещаются в таблице символов (отличной от таблицы символов компилятора). Идентификаторам назначаются адреса в памяти, так что после чтения (1.6) таблица символов может содержать записи, показанные на рис. 1.12. Мы предположили, что для каждого идентификатора выделяется одно слово памяти, состоящее из четырех байт, и адреса начинаются с нулевого адреса.
Идентификатор Адрес
А 0
B 4
Рис. 1.12. Таблица символов ассемблера с идентификаторами из (1.6)
При втором проходе ассемблер вновь сканирует входной поток. В этот раз он переводит каждый код операции в последовательность битов, представляющих операцию на машинном языке, а каждый идентификатор— в адрес, назначенный идентификатору в таблице символов.
В результате второго прохода обычно получается перемещаемый (relocatable) машинный код, что означает, что он может быть загружен в память с любого стартового адреса L. Если L будет добавлено ко всем адресам в коде, то все ссылки будут совершенно корректны. Таким образом, выходной код ассемблера должен различать части инструкций, ссылающиеся на адреса, которые могут быть перенесены.
Пример 1.3
Далее следует гипотетический машинный код, в который переводятся инструкции из (1.6).
0001 01 00 00000000 *
001101 10 00000010 (1.7)
0010 01 00 00000100 *
Инструкция представлена в виде слова, в котором первые четыре бита являются кодом инструкции (0001, 0010 и 0011соответствуют загрузке, сохранению и сложению). Под загрузкой и сохранением подразумевается перемещение из памяти в регистр и наоборот. Следующие два бита определяют используемый регистр; 01 означает, что во всех трех командах используется первый регистр. Два последующих бита определяют "дескриптор". 00 означает режим обычной адресации, при котором последующие восемь бит представляют собой адрес памяти; дескриптор 10 указывает на "непосредственный" режим, когда последующие восемь бит являются операндом. Этот режим используется во второй команде (1.7).
В (1.7) есть также символ "*"— бит перемещаемости — который имеется у каждого операнда в перемещаемом машинном коде. Предположим, что адресное пространство содержит данные, загруженные начиная с адреса L. В этом случае символ * означает, что L должно быть добавлено к адресу операнда. Таким образом, если L=00001111, т.е. 15, то а и b размещаются по адресам 15 и 19. Теперь (1.7) в абсолютном (или непереме-щаемом) машинном коде будет выглядеть как
0001 01 00 00001111
001101 10 00000010 (1.8)
0010 01 00 00010011
Заметьте, у второй команды в (1.7) нет связанного бита перемещаемости, поэтому во второй команде прибавления L не происходит (так как, по сути, восьмибитовое значение представляет собой не адрес 2, а константу 2).
Дата добавления: 2015-11-30; просмотров: 52 | Нарушение авторских прав