Генерация кода
Занесение фактических параметров в магазин MOVE BP, LP
SUB Delta, LP JSR A
Здесь Delta - размер локальных вызывающей подпрограммы плюс двойная длина слова. Магазин после этого принимает состояние, изображенное на рис. 9.3. Предполагается, что регистр LP уже сохранен среди сохраняемых регистров, причем самым первым (сразу после локальных переменных).
После выхода из подпрограммы в вызывающей подпрограмме выполняется команда
MOVE (LP), LP
которая восстанавливает старое значение статической цепочки. Если выход осуществлялся из подпрограммы 1-го уровня, эту команду выполнять не надо, поскольку для 1-го уровня нет статической цепочки.
При вызове подпрограммы меньшего, чем вызывающая, уровня выполняются следующие команды:
Занесение фактических параметров в магазин MOVE (LP), LP /* столько раз, какова разность уровней вызывающей и вызываемой ПП */ JSR A
Тем самым устанавливается статический уровень вызываемой подпрограммы. После выхода из подпрограммы выполняется команда
MOVE -Delta(BP), LP
восстанавливающая статический уровень вызывающей подпрограммы.
Тело подпрограммы начинается со следующих команд:
LINK BP , -размер"локальных MOVEM -(SP)
Команда LINK BP, размер_локальных эквивалентна трем командам:
MOVE BP, -(SP) MOVE SP, BP ADD -размер_локальных, SP
Команда MOVEM сохраняет в магазине регистры. В результате выполнения этих команд магазин приобретает вид, изображенный на рис. 9.1.
Выход из подпрограммы осуществляется следующей последовательностью команд:
MOVEM (SP)+ UNLK BP RTD размер_фактических
Команда MOVEM восстанавливает регистры из магазина.
Команда UNLK BP эквивалентна такой последовательности команд:
MOVE BP,SP MOVE (SP),BP ADD #4, SP /* 4 - размер слова */
Команда RTD размер_фактических, в свою очередь, эквивалентна последовательности
ADD размер"фактических+4, SP JMP -размер"фактических-4(SP)
После ее выполнения магазин восстанавливается до состояния, которое было до вызова.
В зависимости от наличия локальных переменных, фактических параметров и необходимости сохранения регистров каждая из этих команд может отсутствовать.
Организация магазина с дисплеем
Рассмотрим теперь организацию магазина с дисплеем. Дисплей - это массив (DISPLAY), i -й элемент которого представляет собой указатель на область активации последней вызванной подпрограммы i -го статического уровня. Доступ к переменным самой внутренней подпрограммы осуществляется через регистр BP. Дисплей может быть реализован либо через регистры (если их достаточно), либо через массив в памяти.
При вызове процедуры следующего (по отношению к вызывающей) уровня в дисплее отводится очередной элемент. Если вызывающая процедура имеет статический уровень i, то при вызове процедуры уровня j <= i элементы дисплея j,...,i должны быть скопированы (обычно в стек вызывающей процедуры), текущим уровнем становится j и в DISPLAY[j] заносится указатель на область активации вызываемой процедуры. По окончании работы вызываемой процедуры содержимое дисплея восстанавливается из стека.
Иногда используется комбинированная схема - дисплей в магазине. Дисплей хранится в области активации каждой процедуры. Формирование дисплея для процедуры осуществляется в соответствии с правилами, описанными выше.
Отдельного рассмотрения требует вопрос о технике передачи фактических параметров. Конечно, в случае простых параметров (например, чисел) проблем не возникает. Однако передача массивов по значению - операция довольно дорогая, поэтому с точки зрения экономии памяти целесообразнее сначала в подпрограмму передать адрес массива, а затем уже из подпрограммы по адресу передать в магазин сам массив. В связи с передачей параметров следует упомянуть еще одно обстоятельство.
Рассмотренная схема организации магазина допустима только для языков со статически известными размерами фактических параметров. Однако, например, в языке Модула-2 по значению может быть передан гибкий массив, и в этом случае нельзя статически распределить память для параметров. Обычно в таких случаях заводят так называемый "паспорт" массива, в котором хранится вся необходимая информация, а сам массив размещается в магазине в рабочей области выше сохраненных регистров.