Статус нашего сайта: |
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После прочтения директивы 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 просто сохраняла в буфере накопленный двоичный код и записывала файл на диск большими кусками — это снизит нагрузку на диск. Исходный оператор и выходной (объектный) код, полученный из него (в ше-стнадцатеричной системе), можно напечатать или поместить в буфер, чтобы напечатать потом. После смены значения счетчика адресов команд вызывается следующий оператор. |