Скачиваний:
10
Добавлен:
01.05.2014
Размер:
159.74 Кб
Скачать
    1. Особенности работы с данными в стеке исполнения

Будем полагать, что в стеке исполнения в языке ассемблера могут находиться как указатели на переменные, так и сами значения переменных. При исполнении конкретных операторов (например, оператора вычитания целых чисел @SUBINT) удобно делать какие-то предположения об элементах в стеке. Оказывается, что для большинства операторов удобно делать предположения о том, что в стеке исполнения находятся не указатели на элементы, а их значения.

Для пояснения рассмотрим пример в ПОЛИЗ:

x

y

@SUBINT

z

@SUBINT

В данном случае, если бы мы предполагали, что в стеке исполнения находятся указатели на складываемые переменные, то после исполнения последовательности

x

y

@SUBINT

было бы получено число, соответствующее значению (x-y) – и для того, чтобы следующий оператор @SUBINTудовлетворял контракту, пришлось бы создать временную переменную и поместить в нее значение (x-y), после чего поместить указатель на эту временную переменную в стек. Если бы подобные операции выполнялись, например, в цикле, то такая схема привела бы к значительному усложнению управления памятью.

Гораздо удобнее полагать, что большинство операций принимают в качестве аргументов значения и возвращают значения. Но не всегда, когда на входной ленте встречается x, предполагается, что это значение переменнойx. Например, в таком случае это не так:

x

5

@SET

Для того чтобы выполнить операцию присваивания, нам надо знать адрес переменной x. Поэтому мы будем использовать автоматическое разыменование указателей. Поскольку на этапе компиляции мы перед переводом каждой операции в ассемблер знаем, что именно должно находиться в стеке, указатель или значение, значит, непосредственно перед переводом операции мы можем добавить к переводу операцию разыменования указателя, которая заменит указатель, находящийся в стеке на значение, находящееся по его адресу.

Для того чтобы осуществить это, используется промежуточный стек исполнения ПОЛИЗ внутри транслятора. Каждый элемент этого стека имеет тип (указатель на переменную, значение переменной или метка), а также полную информацию об используемом типе данных (в случае, если элемент не метка).

    1. Описание перевода элементов полиз в язык ассемблера

КомандаПОЛИЗ

Перевод в ассемблер

Пояснение

x

push offset __variable_x

Положить указатель на переменную (x) в стек ассемблера.

Положить указатель на переменную (x) в промежуточный стек исполнения.

<числовая константа>

push <числовая константа>

Положить значение числовой константы в стек ассемблера.

Положить значение числовой константы в промежуточный стек исполнения.

<именная константа>

push <значение именной константы>

Положить значение именной константы в стек ассемблера.

Положить значение именной константы в промежуточный стек исполнения.

<метка>

Положить имя метки в промежуточный стек исполнения.

    1. Пример работы с данными в стеке исполнения

Рассмотрим пример в ПОЛИЗ, где x– это переменная целочисленного типа:

x

5

@SUBINT

Он будет последовательно следующим образом:

  1. Сначала промежуточный стек исполнения пуст.

  2. Встретили во входном файле x,

    1. Обратились к таблице переменных и убедились в том, что это переменная.

    2. Написали pushoffset__variable_xв выходной файл.

    3. Поместили в стек исполнения элемент с типом указатель на переменную и типом данных, соответствующим переменной xв таблице переменных.

  3. Встретили во входном файле 5

    1. Написали push5 в выходной файл.

    2. Поместили в стек исполнения элемент с типом значение и типом данных integer.

  4. Встретили во входном файле @SUBINT– функцию, которая вычитает два целых числа.Eе контракт предполагает, что в стеке исполнения находится два целочисленных значения.

    1. Привели стек к виду, когда на верху лежат два целочисленных значения. На верхушке стека лежит целочисленное значение (5), вторым элементом лежит указатель (на переменную x). Чтобы реальный стек соответствовал контракту функции надо выполнить разыменование указателя:

      1. Во временный регистр извлекается верхушка стека (в выходной файл пишется popeax).

      2. Выполняется преобразование указатель к значению для новой верхушки стека (в выходной файл пишется вызов макроса __evaluate_integer).

      3. Извлеченное ранее целочисленное значение помещается назад (в выходной файл пишется pusheax).

    2. В выходной файл записывается вызов библиотечной функции ___sub_integer, соответствующей команде@SUBINT ПОЛИЗ.

    3. Первые два элемента удаляются из стека исполнения.

    4. В стек исполнения помещается новый элемент с типом значение и типом данных integer(по контракту, команда@SUBINTкладет в стек значение целочисленного типа).

В выходном файле переведенный фрагмент будет выглядеть так:

push offset __variable_x ; x

push 5 ; 5

pop eax

__evaluate_integer

push eax

call __sub_integer ; @ADDINT

add esp, 4

Соседние файлы в папке Бяша