Московский государственный университет имени М.В.Ломоносова
Опубликован: 03.10.2006 | Доступ: свободный | Студентов: 1223 / 79 | Длительность: 09:08:00
Специальности: Программист
Лекция 4:

Управление подпрограммами

< Лекция 3 || Лекция 4: 12 || Лекция 5 >
Аннотация: Дается определение подпрограммы и записи активации. Рассматриваются механизмы последовательного и рекурсивного вызова подпрограмм.

Простые подпрограммы

Определение и активация подпрограмм

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

Для выполнения любого выражения транслятор преобразует его в некоторый код, который или может быть сразу аппаратно интерпретируем (машинный язык) или программно интерпретируем (использование интерпретатора).

Для выполнения подпрограммы производится ее активация, в результате чего создаются:

  • сегмент кода, содержащий выполняемый код и константы;
  • сегмент данных, называемый также записью активации, содержащей локальные переменные и параметры.

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

Каждая активация подпрограммы использует один единожды созданный сегмент кода.

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

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

При выполнении программы текущая выполняемая команда идентифицируется двумя указателями:

  • CIP-указатель (current instruction pointer) является указателем текущей команды сегмента кода;
  • CEP-указатель (current environment pointer) является указателем текущей записи активации. CEP-указатель иногда также называется указателем текущей среды, так как определяет среду всех объектов данных, используемых подпрограммой.

При выполнении программы интерпретатор выбирает команду по CIP-указателю, увеличивает значение этого указателя и выполняет выбранную команду. Если при выполнении команды был выполнен безусловный переход или вызов подпрограммы, то значение CIP-указателя опять изменяется. Значение переменной, используемой в подпрограмме, определяется по CEP-указателю, идентифицирующему конкретную запись активации.

Последовательный вызов подпрограмм

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

Перед переходом на подпрограмму текущие значения CIP- и CEP-указателей сохраняются. Выполнение программы начинается с присваивания CEP-указателю адреса записи активации, а CIP-указателю - ссылки на первую команду сегмента кода главной программы. При каждом вызове подпрограммы создается новая запись активации этой подпрограммы, и значение CEP-указателя устанавливается на эту запись активации, а значение CIP-указателя - на первую команду фрагмента кода подпрограммы.

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

Место сохранения значений CIP-указателя и CEP-указателя иногда называют точкой возврата. Точка возврата представляет собой системный объект, сохраняемый, как правило, в записи активации.

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

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

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

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

Стек создается в свободной области памяти. При вызове подпрограммы созданная запись активации помещается в стек. При этом значение указателя стека увеличивается с учетом размера выделяемого пространства. При удалении записи активации значение указателя стека уменьшается с учетом освобождаемого пространства. Выделение и освобождение памяти в стеке происходит с одного конца и фиксируется указателем стека.

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

На рисунке 4.1 представлена организация памяти, используемая при выполнении программы на языке С.

Организация памяти, используемая при выполнении программы на языке С.

Рис. 4.1. Организация памяти, используемая при выполнении программы на языке С.

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

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

< Лекция 3 || Лекция 4: 12 || Лекция 5 >