Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Glava14 r.doc
Скачиваний:
2
Добавлен:
01.07.2025
Размер:
548 Кб
Скачать
☆

Стековая организация дисплея памяти процедуры (функции)

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

Тогда при вызове процедуры необходимо выполнить следующие действия:

--- поместить в стек все параметры процедуры;

--- запомнить в стеке адрес возврата и передать управление вызываемой процедуре;

--- запомнить в стеке значение базового регистра;

--- запомнить состояние регистра стека в базовом регистре;

--- в начале выполнения вызываемой процедуры разместить в стеке все необходимые ей локальные данные.

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

--- выбрать из стека все локальные данные процедуры;

--- выбрать из стека значение базового регистра;

--- выбрать из стека адрес возврата;

--- передать управление по адресу возврата и выбрать из стека все параметры процедуры.

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

Ha рис. 14.2 показано, как изменяется содержание стека параметров при выполнении трех последовательных вызовов процедур: сначала процедуры A, затем процедуры B и снова процедуры A. При вызовах стек заполняется, а при возврате из кода процедур — освобождается в обратном порядке. Из рис. 14.2 видно, что при рекурсивном вызове все локальные данные последовательно размещаются в стеке и при этом каждая процедура работает только со своими данными. Более того, такая схема легко обеспечивает поддержку вызовов вложенных процедур, которые допустимы, например, в языке Pascal. Стековая организация памяти получила широкое распространение в современных компиляторах. Практически все существующие ныне языки высокого уровня предполагают именно такую схему организации памяти, ее также используют и в программах на языках ассемблера. Широкое распространение стековой организации дисплея памяти процедур и функций тесно связано также с тем, что большинство операций, выполняемых при вызове процедуры в этой схеме, peaлизованы в виде соответствующих машинных команд во многих современных вычислительных системах. Это, как правило, все операции со стеком параметров, а также команды вызова процедуры (с автоматическим сохранением адреса возврата в стеке) и возврата из вызванной процедуры (с выборкой адреса возврата из стека). Такой подход значительно упрощает и ускоряет выполнение вызовов при стековой организации дисплея памяти процедуры (функции).

Стековая организация дисплея памяти процедуры позволяет организовать рекурсию вызовов (в отличие от статической схемы) и имеет все преимущества перед динамической схемой. Однако у этой схемы есть один существенный недостаток — память, отводимая под стек параметров, используется неэффективно. Очевидно, что стек параметров должен иметь размер, достаточный для хранения всех параметров, локальных данных и адресов при самом глубоком вложенном вызове процедуры в результирующей программе. Как правило, ни компилятор, ни разработчик программы не могут знать точно, какая максимальная глубина вложенных вызовов процедур возможна в программе. Следовательно, не известно заранее, какая глубина стека потребуется результирующей программе во время ее выполнения. Размер стека обычно выбирается разработчиком программы «с запасом»1, так, чтобы гарантированно обеспечить любую возможную глубину вложенных вызовов процедур и функций. C другой стороны, большую часть времени своей работы результирующая программа не использует значительную часть стека, значит, и часть оперативной памяти компьютера не используется, так как стек параметров сам по себе не может быть использован для других целей.

Стековая организация дисплея памяти процедур и функций присутствует практически во всех современных компиляторах. Тем не менее процедуры и функции, построенные с помощью одного входного языка высокого уровня, не всегда могут быть использованы в программах, написанных на другом языке. Дело в том, что стековая организация определяет основные принципы организации дисплея памяти процедуры, но не определяет механизм реализации данной схемы. B разных входных языках детали реализации этой схемы могут отличаться порядком помещения параметров процедуры в стек и извлечения из него. Эти вопросы определяются в соглашениях о вызове и передаче параметров, принятых в различных входных языках программирования.

Параметры могут помещаться в стек в прямом порядке (в порядке их следования в описании процедуры) или в обратном порядке. Извлекаться из стека они могут либо в момент возврата из процедуры (функции), либо непосредственно после возврата2. Кроме того, для повышения эффективности программ и увели-

1 K сожалению, нет точных расчетных методов для определения требуемого размера стека. Разработчик обычно оценивает его приближенно, исходя из логики результирующей программы. Когда во время отладки программы возникают сообщения о недостатке объема стека (а в них имеется в виду именно стек параметров), то размер стремятся значительно увеличить. C другой стороны, очень большой объем необходимого стека параметров может говорить о невысоком качестве программы. Если объем доступной памяти под стек ограничен (например, в MS-DOS — не более 64 Кбайт), это ведет к ограничению допустимой вложенности рекурсий, а бесконечная рекурсия всегда ведет к переполнению стека параметров.

2 Существуют два общепринятых соглашения о вызове и передаче параметров: соглашение языка Pascal и соглашение языка C. B первом случае параметры помещаются в стек в прямом порядке и извлекаются из стека в момент выполнения возврата из процедуры (функции) — то есть внутри самой процедуры (функции); во втором случае параметры поменІаются в стек в обратном порядке, а извлекаются из стека после выполнения возврата из функции — то есть непосредственно после выполнения вызова в вызывающем коде.

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

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

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