Р.У. Себеста - Основные копцепции языков программирования (2001) (1160794), страница 104
Текст из файла (страница 104)
В примере, показанном выше, редактор связей вызывался ::я модуля МА1И. Редактор связей должен был найти машинный код программ А, В и С = месте с их экземплярами активационных записей и загрузить в память вместе с кодом " зудя МА?И. Затем он должен был вставить все целевые адреса лля вызовов подпрогзчм А. В и С, а также вызовов всех библиотечных подпрограмм в подпрограммах А, В, и '..'А7М.
Кроме того, все ссылки на переменные в СОММОМ-блоках должны были быть :менены соответствующими адресами. Во многих случаях ссылки на нелокальные пе: ченные обрабатывают с помощью относительной адресации в блоке, избегая необхо'.мости вставки адресов. В языке ГОйТВА)Ч 90 подпрограммы могут быть вложенными (с помощью статиче.. го обзора) и рекурсивными. Это приводит к тому, что их реализация становится по. тей на язык А1.ОО)..
Методы реализации этих языков подробно обсуждаются в сле. юшем разделе. 9.3. Реализация подпрограмм на языках, подобных языку АЕООЕ Рассмотрим реализацию связывания подпрограмм в языках со статическим обзором . чных, подобных языку А1.ОО).. — Рааса!, Ада, ЕОйТКАХ 90 и Ое1рп1, основное вни.чне уделяя операциям вызова и возврата управления во все более усложняющихся сицнях. Детально описываются два связанных между собой, но разных подхода к реали: пн доступа к нелокальным переменным, называемых статическиии цепочками ::абс спа1пз) и индикатораии (дврауз).
Несмотря на то что в языках С, С++ и )ача не допускаются вложенные подпрограм-:. нх реализация похожа на реализацию других языков со статическим обзором дан- л. Отличие заключается в поддержке ссылок на нелокальные переменные, которая жет быть намного проще, если запрещаются вложенные программы. 9.3.1. Более сложные залиси активации Связывание подпрограмм в языках, подобных языку А).ОО)., осуществляется более кным образом, чем связывание подпрограмм в языке ГОКТВАХ 77.
Это происходит :ледуюшим причинам. ° Обычно параметры могут передаваться двумя разными способами. Например, во многих языках они передаются по значению или по ссылке. ° Переменные, объявленные в подпрограммах, часто являются динамическими. ° Рекурсия добавляет возможность одновременно выполнять несколько активаций подпрограммы. Это означает, что одновременно может существовать несколько экземпляров подпрограммы, выполняющихся частично, активируюшихся с помощью одного внешнего вызова подпрограммы и нескольких рекурсивных вызовов. Следовательно, для рекурсии требуется несколько экземпляров записей активации.
по одной на каждую активацию подпрограммы, которые могут существовать 391 3. Реализация подпрограмм на языках, подобных языку АЮО). одновременно. Для каждой активации нужна своя собственная копия формального параметра и динамически размещаемые локальные переменные вместе с адресами возврата. ° В языках, подобных языку А(.001., лля лоступа к нелокальным переменным используется статический обзор данных. Поддержка такого доступа к нелокальным переменным должна быть частью механизма связывания подпрограмм. Формат записи активации лля данной подпрограммы в языках со статическим обзором данных во время компиляции уже известен.
В процедурах языка Рааса! размер записей активации также известен, поскольку все локальные данные процедуры имеют фиксированный размер. Это условие не выполняется в некоторых других языках, в которых размер локального массива может зависеть от значения фактического параметра. В этих случаях формат записи активации является статическим, а ее размер — динамическим. В языках, подобных языку А) 00), экземпляры записей активации должны создаваться динамически. Типичная запись активации лля языка, подобного языку АЕОО(., привелена на рис, 9.3.
Ввршина стем Рис. 9З. Типичная зались активации в языке, падабнач языку АьсзОЕ Поскольку адрес возврата, статическая связь, линамическая связь и параметры помещаются в запись активации вызывающим модулем, они должны быть первыми элементами записи активации. В этой главе мы предполагаем, что стек растет вверх. Следовательно, адрес возврата окажется на дне записи активации.
Адрес возврата часто содержит указатель на сегмент кода вызывающего модуля и относительный адрес команды, следующей за вызовом в этом сегменте кола. Статическая связь (згабс йпй), которую иногда называют указателем статического обзора, указывает на дно экземпляра записи активации статического предка. Она используется для доступа к не- локальным переменным.
Статические связи детально обсуждаются в разделе 9.3.4. Динамическая связь (дупапк йпй) — это указатель на вершину экземпляра записи активации вызывающего модуля. В языках со статическим обзором данных эта связь используется при разрушении текущего экземпляра записи активации после выполнения процедуры.
Динамическая связь нужна, поскольку в некоторых случаях в стеке находятся переменные, помещенные туда подпрограммой после записи активации. Например, там могут находиться временные переменные, необходимые для машинного кода подпрограммы. Таким образом, даже зная размер записи активации, его нельзя просто вычесть из указателя на вершину стека для того, чтобы удалить запись, Фактические параметры в записи активации являются значениями, или адресами, задаваемыми вызывающим модулем.
Глава 9. Реализация подпрограмм 396 Локальные скалярные переменные связываются с ячейками памяти в экземпляре за-иси алтивации. Локальные переменные, представляюшие собой структуры, иногда разешаются в произвольном месте, а в запись активации заносятся только их дескрипторы с казатели на места их хранения. Локальные переменные размешаются в памяти и мо— т инициализироваться вызываемой подпрограммой, поэтому они заносятся в запись сьтнааЦИИ ПОСЛЕДНИМИ.
Рассмотрим следуюшую скелетную процедуру на языке Разсай ргооесгцге вцЬ (ивг Соеа1 с геа1; рагс с йпфедег) Г иаг 11зс : аггау ~1..5] ог йпседегг зцас: геа1; Ьедйп епсзг Запись активации подпрограммы ацЬ показана на рис. 9.4. 1сьс 151 1141 141 1свс !31 1сБС 121 11ьс 111 рагс сосас Рис. 9.4. Запись активации процедуры зиЬ При активации процедуры динамически создается экземпляр записи активации этой -зоцедуры. Как указывалось ранее, формат этой записи во время компиляции является :,сксированным, хотя размер записи в других языках, отличающихся от языка Рааса!, зияет зависеть от вызова. Поскольку семантика вызова и возврата указывает, что под-=ограмма, вызванная последней, завершается первой, вполне резонно поместить создазсечые экземпляры записей активации в стек.
Этот стек является частью системы под'."жки выполнения программ и поэтому называется стеком выполняемой программы .3. Реализация подпрограмм иа языках, подобных языку Аь001 (гцп-((ше з(аск), хотя мы будем называть его просто стеком. Каждая активация процедуры, независимо от того, является ли эта процедура рекурсивной или нет, создает новый экземпляр записи активации в стеке.
Это обеспечивает требуемое разделение копий параметров, локальных переменных и адресов возврата. Напомним, что„как указывалось в главе 8, подпрограмма является активной, начиная с момента ее вызова и заканчивая моментом ее завершения. Когда подпрограмма становится неактивной. ее локальные области видимости перестают существовать и ее среда ссылок больше не имеет смысла. Таким образом, в этот момент ее экземпляр записи активации разрушается. 9.3.2.
Пример без рекурсии и нелокольных ссылок Вследствие сложности реализации связывания подпрограмм мы рассмотрим их в несколько этапов. Во-первых, изучим пример программы, в которой нет обращений к не- локальным переменным и рекурсивных вызовов. В этом примере не используется статическая связь. Затем мы обсудим, как реализовать рекурсию и доступ к нелокальным переменным. Рассмотрим следующий скелетный пример программы: ргодгаа МА1И 1; чаг Р : геа1; ргооес(пге А(Х : спседег); чаг Х: Ьоо1еап; ргосес(иге С(0 : Ьоо1еап) Ьедз.п ( С ) с 3 епс(; ( С Ьедяп ( А ] с — 2 С(У) ) епс(; ( А ) ргосес(цге В (В: геа1]; чаг Я, Т : спведег; Ьедхп ( В ! с 1 А(Я) г () (в] Ьедсп ( МА1Н 1 В(Р)) епо.