- •1. Цель работы 17
- •Введение
- •3. Примеры
- •3.1. Лексический анализатор целочисленных констант языка с
- •3.2. Лексический анализатор для поиска строк в исходном тексте программы
- •4. Содержание работы
- •5. Контрольные вопросы
- •3. Примеры
- •3.1. Схемы су – перевода
- •3.2. Схема су–перевода дерева операций на язык ассемблера
- •3.3. Схема су - перевода дерева операций в последовательность триад
- •3.4. Методы оптимизации кода
- •3.5. Свертка объектного кода
- •3.6. Исключение лишних операций
- •4. Содержание работы
- •5. Контрольные вопросы
- •Список литературы
- •450000, Уфа - центр, ул. К. Маркса, 12
3.2. Схема су–перевода дерева операций на язык ассемблера
В качестве языка ассемблера возьмем язык ассемблера процессоров типа Intel 80x86. При этом будем считать, что операнды могут быть помещены в 16-разрядные регистры процессора, а в коде результирующей объектной программы могут использоваться регистры АХ (аккумулятор) и DX ( регистр данных), а также стек для хранения промежуточных результатов.
Функцию, реализующую перевод узла дерева в последовательность команд ассемблера, назовем Code. Входными данными функции должна быть информация об узле дерева операций. В ее реализации на каком – либо языке программирования эти данные можно представить в виде указателя на соответствующий узел дерева операций. Входными данными является последовательность команд языка ассемблера. Будем считать, что она передается в виде строки, возвращаемой в качестве результата функции.
Тогда четырем формам текущего узла дерева для каждой арифметической операции будут соответствовать фрагменты кода на языке ассемблера, приведенные в табл. 2.1.
Таблица 2.1
Вид узла дерева |
Результирующий код |
Примечание |
|
mov ax, oper1 act ax, oper2 |
act – команда соответствующей операции oper1, oper2 – операнды (листья дерева) |
|
Code (Узел 2) mov dx, ax mov ax, oper1 act ax, dx |
Узел 2 – нижележащий узел (не лист) дерева Code (Узел 2) – код, порождаем. процедурой для нижележащего узла |
|
Code (Узел 2) act ax, oper2 |
Code (Узел 2) – код, порождаем. процедурой для нижележащего узла |
|
Code (Узел 2) push ax Code (Узел 3) mov dx, ax pop ax act ax, dx |
push и pop – команды сохранения результатов в стеке и извлечения результатов из стека |
Каждой допустимой арифметической операции соответствует своя команда на языке ассемблера. Если взять в качестве примера операции сложения, вычитания, умножения и деления, то им соответствуют команды add, sub, mul и div. В ассемблере Intel 80x86 от типа операции зависит также синтаксис команды (операции mul и div в качестве первого операнда всегда предполагают регистр процессора AX, который не нужно указывать в команде).
Код, порождаемый для операции присвоения результата, отличается от кода, порождаемого для арифметических операций. Кроме того, семантика языка требует, чтобы в левой части операции присвоения всегда был операнд, поэтому для нее возможны только два типа узла дерева, влекущие порождение кода (табл. 2.2)
Таблица 2.2
Вид узла дерева |
Результирующий код |
Примечание |
|
mov ax, oper1 mov oper1, ax |
oper1, oper2 – операнды (листья дерева) |
|
Code (Узел 2) mov oper1, ax
|
Узел 2 – нижележащий узел (не лист) дерева Code (Узел 2) – код, порождаем. процедурой для нижележащего узла |
Рассмотрим в качестве примера выражение A:=B*C+D-B*10. Ему будет соответствовать следующее дерево вывода (рис. 2.).
Рис. 2. Дерево операций
Построим последовательность команд языка ассемблера по шагам рекурсии. Согласно принципу СУ – перевода, построение начинается от корня дерева.
Шаг 1: Code (U2)
mov A, ax
Шаг 2: Code (U3)
push ax
Code (U5)
mov dx, ax
pop ax
sub ax, dx
mov A, ax
Шаг 3: Code (U4)
add ax, D
push ax
Code (U5)
mov dx, ax
pop ax
sub ax, dx
mov A, ax
Шаг 4: mov ax, B
mul C
add ax, D
push ax
Code (U5)
mov dx, ax
pop ax
sub ax, dx
mov A, ax
Шаг 5: mov ax, B
mul C
add ax, D
push ax
mov ax, B
mul 10
mov dx, ax
pop ax
sub ax. dx
mov A, ax
Полученный код может быть оптимизирован.