Генерация кода
Определение 4.13. Непосредственная генерация кода – это процесс порождения машинных команд по записи программы на промежуточном языке.
Задача генерации машинного кода обычно делится на две более простые задачи:
1) расчленение операций промежуточного языка на операции, эквивалентные машинным, и представление программы в виде псевдокода;
2) формирование компьютерных команд по псевдокоду.
При формировании псевдокода по промежуточной программе можно использовать заготовки. Продемонстрируем данную методику на примере преобразования дерева операций в код на языке ассемблера.
В качестве языка ассемблера возьмем язык ассемблера процессоров типа Intel 80x86. При этом будем считать, что операнды могут быть помещены в 16-разрядные регистры процессора и в коде результирующей объектной программы могут использоваться регистры АХ (аккумулятор) и DX (регистр данных), а также стек для хранения промежуточных результатов.
Введем обозначения:
1) Code(U) - функция, реализующая перевод данного узла U дерева в последовательность команд ассемблера;
2) operl, oper2 - операнды (листья дерева);
3) U1, U2 – узлы дерева, не являющиеся листьями;
4) act - обозначение одной из арифметических операций - сложения (+), вычитания (-), умножения (*) и деления (/), которым будут соответствовать команды ассемблера add, sub, mul и div.
Тогда четырём возможным формам текущего узла дерева для каждой арифметической операции будут соответствовать фрагменты кода на языке ассемблера, приведенные в таблице 4.5.
Таблица 4.5 - Преобразование узлов дерева операций в код на языке ассемблера для арифметических операций
Вид узла дерева |
Результирующий код |
mov ax, oper1 |
|
Code (U2) |
|
Code (U1) |
|
Code (U1) |
Семантика оператора присвоения требует, чтобы в левой части операции всегда был операнд, поэтому для нее возможны только два типа узлов дерева, влекущие порождение кода (два других типа узлов должны приводить к сообщению об ошибке). Заготовки для этой операции приведены в таблице 4.6.
Таблица 4.6 - Преобразование узлов дерева операций в код на языке ассемблера для операции присвоения
Вид узла дерева |
Результирующий код |
mov ax, ореr2 |
|
|
Code (U2) |
Пример 4.11. Рассмотрим в качестве примера выражение X:=Y*2-Z/3. Соответствующее ему дерево операций приведено на рисунке 4.7.
Рисунок 4.7 - Дерево операций для выражения X:=Y*2-Z/3
Построим последовательность команд языка ассемблера, соответствующую дереву операций. Пронумеруем узлы дерева согласно методу рекурсивного спуска по направлению от корня к листьям в порядке слева направо. Последовательность построения цепочки команд языка ассемблера по шагам рекурсии имеет вид.
Шаг 1. Code(U2) Шаг 2. Code(U3) |
Шаг 3. mov ax, Y |
Шаг 4. mov ax, Y |