Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лаб_раб_1_4.doc
Скачиваний:
16
Добавлен:
10.11.2019
Размер:
622.08 Кб
Скачать

Построение ассемблерного кода по дереву вывода

В качестве языка ассемблера возьмем язык ассемблера процессоров типа Intel 80x86. При этом будем считать, что операнды могут быть помещены в 16-разрядные регистры процессора и в коде результирующей объектной программы могут использоваться регистры AX (аккумулятор) и DX (регистр данных), а также стек для хранения промежуточных результатов.

Тогда четырем формам текущего узла дерева будут соответствовать следующие фрагменты кода на языке ассемблера (табл. 5):

Таблица 5.

Преобразование типовых узлов дерева вывода в код на языке ассемблера

Вид узла дерева

Результирующий код

Примечание

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

Code(Узел 2) - код, порождаемый процедурой для нижележащего узла

Code(Узел 3) - код, порождаемый процедурой для нижележащего узла

push и pop - команды сохранения результатов в стеке и извлечения результатов из стека

Рассмотрим пример дерева вывода для выражения A := B*C + D - B*10 на рис. 5 и соответствующий ему фрагмент кода на языке ассемблера, построенный по описанным выше правилам (обратите внимание, что для операции присваивания используется отдельный код, не подпадающий под общие правила):

Рис. 5. Дерево вывода для арифметического выражения.

Шаг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 ax,C

add ax,D

push ax

Code(U5)

mov dx,ax

pop ax

sub ax,dx

mov A,ax ;операция присваивания

Шаг 5: mov ax,B

mul ax,C

add ax,D

push ax

mov ax,B

mul ax,10

mov dx,ax

pop ax

sub ax,dx

mov A,ax ;операция присваивания

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

Обычно такие проблемы решаются таким образом, что вместо команд непосредственно языка ассемблера используются команды некоторого близкого к нему промежуточного псевдокода. Большинство этих команд один в один отображаются затем в команды языка ассемблера, другие же однозначно преобразуются в фиксированную последовательность команд.