Статус
нашего
сайта:
ICQ Secrets Center is Online  ICQ Information Center


ICQ SHOP
     5-значные
     6-значные
     7-значные
     8-значные
     9-значные
     Rippers List
ОПЛАТА
СТАТЬИ
СЕКРЕТЫ
HELP CENTER
OWNED LIST
РОЗЫСК!New!
ICQ РЕЛИЗЫ
Протоколы ICQ
LOL ;-)
Настройка компьютера
Аватарки
Смайлики
СОФТ
     Mail Checkers
     Bruteforces
     ICQTeam Soft
     8thWonder Soft
     Other Progs
     ICQ Patches
     Miranda ICQ
ФорумАрхив!
ВАШ АККАУНТ
ICQ LiveJournal

Реклама

Наш канал:

irc.icqinfo.ru

Таненбаум Э.- Архитектура компьютера. стр.410


Таненбаум Э.- Архитектура компьютера. стр.410

После прочтения директивы END первый проход завершается. В этот момент можно сохранить таблицу символических имен и таблицу литералов, если это необходимо. В таблице литералов можно произвести сортировку и удалить дубликаты.

Второй проход

Цель второго прохода — создать объектную программу и напечатать протокол ассемблирования (если нужно). Кроме того, при втором проходе должна выводиться информация, необходимая для компоновки в один исполняемый файл процедур, которые ассемблировались в разное время. В листинге 7.10 показана процедура для второго прохода.

Листинг 7.10. Второй проход простого ассемблера

public static void pass_two() { // Эта процедура - второй проход ассемблера

boolean morejnput = true; // флаг, останавливающий второй проход

String line, opcode; // поля команды

int location_counter, length, type; // переменные final int END_STATEMENT = -2; // сигналы окончания ввода

final int MAX_C0DE =16; // максимальное число байтов в команде

byte code[] = new byte[MAX_CODE]; // число байтов в команде

// в порожденном коде

location_counter =0; // ассемблирование первой

// команды в адресе О

while (morejnput) { // morejnput с помощью директивы END

// получает значение "ложь"

type = read_type(); // считывание поля типа следующей строки

opcode = read_opcode(); // считывание поля кода операции

//в следующей строке

length = read_length(); // считывание поля длины

// в следующей строке

line = read_line(); // считывание самой входной строки

if (type != 0) { // тип 0 указывает на комментарий

switch(type) { // порождение выходного кода

case 1:eva1_typel(opcode, length, line, code); break; case 2: evalj:ype2(opcode, length, line, code); break; // другие варианты

}

}

write_output(code); // запись двоичного кода

writejisting(code, line); // вывод на печать одной строки

location_counter = location_counter + length; // обновление счетчика

// адресов команд if (type == END_STATEMENT) { // завершен ли ввод? more_input я false; // если да. то выполняем

// служебные операции finish_up(); // завершение

}

}

}

Процедура второго прохода похожа на процедуру первого: строки считывают-ся по одной и обрабатываются тоже по одной. Поскольку мы записали в начале каждой строки тип, код операции и длину (во временном файле), все они считы-ваются и, таким образом, нам не нужно проводить анализ строк во второй раз. Основная работа по порождению кода выполняется процедурами evaltypel, eva!_type2 и т. д. Каждая из них обрабатывает определенную модель (например, код операции и два регистра-операнда). Полученный в результате двоичный код команды сохраняется в переменной code. Затем совершается контрольное считывание. Желательно, чтобы процедура writecode просто сохраняла в буфере накопленный двоичный код и записывала файл на диск большими кусками — это снизит нагрузку на диск.

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


⇐ Предыдущая страница| |Следующая страница ⇒

.