Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lab_tlpt_12_7.doc
Скачиваний:
1
Добавлен:
01.03.2025
Размер:
494.08 Кб
Скачать
  1. Практическая часть.

Лабораторная работа № 8. Генератор кода 5.1.

Генерирование общих фрагментов кода, объявления переменных.

Так как наш транслятор является однопроходным, методы генератора кода будут вызываться из методов синтаксического анализатора. По мере выполнения синтаксического разбора будет генерироваться и ассемблерный код. Для удобства будем хранить его в массиве строк. В классе CodeGenerator объявим массив строк и целочисленную переменную, хранящую текущий индекс для его правильного заполнения.

private static string[] code = new string[MAX_NUMBER_STRINGS];

private static int codePointer = 0;

Ключевым методом генератора кода будет метод добавитьИнструкцию(), добавляющий одну строку ассемблерного кода.

добавитьИнструкцию( инструкция )

{

код[указатель++] = инструкция;

}

Для ассемблерных программ некоторая часть кода является общей: объявление сегментов данных, кода и стека; инструкции завершения сегмента кода и т. д. Декларирование общих участков кода вынесем в отдельные функции.

Объявление сегмента данных (секции объявления переменных):

декларироватьСегментДанных()

{

добавитьИнструкцию( "data segment para public \"data\"" );

}

Объявление сегментов стека и кода:

декларироватьСегментыСтекаИКода()

{

добавитьИнструкцию( "PRINT_BUF DB ' ' DUP(10)" );

добавитьИнструкцию( "BUFEND DB '$'" );

добавитьИнструкцию( "data ends" );

добавитьИнструкцию( "stk segment stack" );

добавитьИнструкцию( "db 256 dup (\"?\")" );

добавитьИнструкцию( "stk ends" );

добавитьИнструкцию( "code segment para public \"code\"" );

добавитьИнструкцию( "main proc" );

добавитьИнструкцию( "assume cs:code,ds:data,ss:stk" );

добавитьИнструкцию( "mov ax,data" );

добавитьИнструкцию( "mov ds,ax" );

}

Объявление завершения основной процедуры:

декларироватьЗавершениеОсновнойПроцедуры()

{

добавитьИнструкцию( "mov ax,4c00h" );

добавитьИнструкцию( "int 21h" );

добавитьИнструкцию( "main endp" );

}

Объявление завершения кода:

декларироватьЗавершениеКода()

{

добавитьИнструкцию( "code ends" );

добавитьИнструкцию( "end main" );

}

Далее необходимо реализовать объявление переменных в ассемблерном коде.

декларироватьПеременные()

{

УзелСвязанногоСписка<Идентификатор> узел = nameTable.получитьИдентификаторы().Первый;

пока( узел != НУЛЛ )

{

добавитьИнструкцию( узел.Значение.Имя + " dw 1" );

узел = узел.Следующий;

}

}

Последним штрихом будет доработка метода SyntaxAnalyzer.компилировать(). Дополним его вызовом реализованных методов генератора кода.

компилировать()

{

CodeGenerator.декларироватьСегментДанных();

LexicalAnalyzer.инициализировать();

разобратьОбъявлениеПеременных();

CodeGenerator.декларироватьПеременные();

CodeGenerator.декларироватьСегментыСтекаИКода();

проверитьЛексему( Lexems.ПереносСтроки );

если( LexicalAnalyzer.текущаяЛексема == Lexems.Begin )

LexicalAnalyzer.разобратьСледующуюЛексему();

LexicalAnalyzer.разобратьСледующуюЛексему();

LexicalAnalyzer. разобратьПоследовательностьИнструкций();

проверитьЛексему( Lexems.End );

CodeGenerator.декларироватьЗавершениеОсновнойПроцедуры();

CodeGenerator.декларироватьЗавершениеКода();

}

Замечания по коду:

  1. Вывод ассемблерного кода на форму необходимо реализовать самостоятельно.

Примеры кода:

Файлы CodeGenerator.cs, SyntaxAnalyzer.cs в проекте.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]