К. Хамахер, З. Вранешич, С. Заки - Организация ЭВМ - 5-е издание (2003) (1114649), страница 24
Текст из файла (страница 24)
100 Глава 2. Машинные команды и программы последовательности чисел. Подпрограмме 1.1БТА1)1) передается адрес первого числа в последовательности и количество ее злементов. Подпрограмма выполняет сложение и возвращает полученную сумму. Ее параметры помещаются в стек процессора, на который указывает регистр БР.
Предположим, что до вызова подпрограммы вершина стека располагается на уровне 1 (рис. 2.26, б). Вызывающая программа помещает в стек адрес Х()М1 и значение и и вызывает подпрограмму 1.1БТАИЭ. Кроме того, команда Са11 помещает в стек адрес возврата из подпрограммы. Теперь вершина стека располагается на уровне 2. стека расположена на уровне 1) №(~П)М1,— (БР) Помещение параметров в стек Ы,-(БР) 1.1БТАПП Вызов по о аммы (Предполагается, что вершина Моче Моче Са11 Моче АаЫ 4(БР),ЯЛМ №8,БР 1.15ТАПП МочеМо1ПР1е КО-К2,-(БР) Моче Моче С!еат АсЫ 1.00Р К1 1.00Р К0,20(БР) (ЯР)+,КО-К2 Помещение результата в стек Восстановление регистров Возврат в вызывающую про~рамму Уровень 3 — в Уровень 2 — в Уровень 1 — в Рис. 2.26. Программа, представленная на рис.
2Л 6, реализована как подпрограмма, с передачей параметров через стек: вызывающая программа и подпрограмма (а); вершина стека в разные моменты времени (О) Песгеглелг ВгзпсЬ>0 Моче Мо теМц!ПР1е Кеозгп 16(БР),К1 20(БР),К2 КО (К2)ч-,КО дпр гр (вершина стека на уровне 2) Сохранение результата Восстановление вершины стека (вершина стека на уровне 1) Сохранение регистров (вершина стека на уровне 3) Инициализация счетчика значением и Инициализация указателя на последовательности чисел Инициализация суммы значением 0 Добавление числа из последовательности чисел 2.9. Подпрограммы 101 Подпрограмма использует три регистра, Поскольку в них могут содержаться данные, принадлежащие вызывающей программе, их содержимое сохраняется в стеке. Для помещения в стек содержимого регистров от КО до К2 мы используем команду МочеМпК1р1е.
Подобные команды имеются у многих процессоров. Теперь вершина стека располагается на уровне 3. С помощью индексной адресации подпрограмма считывает из стека параметры и и ХБМ1. Значение указателя стека при этом не меняется, поскольку на вершине стека по-прежнему располагаются нужные нам элементы данных. Значение н загружается в регистр К1, который будет играть роль счетчика, а адрес ХБМ1 — в регистр К2, который будет служить указателем при сканировании списка значений.
Регистр КО должен содержать результат суммирования. Перед возвратом из подпрограммы содержимое регистра КО помещается в стек, заменяя параметр ХПМ1, который нам больше не нужен. Затем из стека восстанавливается содержимое трех регистров, использовавшихся подпрограммой. Теперь верхним элементом стека является адрес возврата, расположенный на уровне 2. После возврата из подпрограммы вызывающая программа сохраняет результат в памяти по адресу ЗПМ и возвращает вершину стека иа ее исходный уровень, уменьшая значение 5Р на 8. Передача параметров по значению и по ссылке Обратите внимание на то, как передаются параметры ХПМ1 и п (рис.
2.25 и 2.26). Задачей подпрограммы является сложение последовательности чисел. Вместо того чтобы передавать реальные элементы последовательности, вызывающая программа передает подпрограмме адрес ее первого элемента. Эта технология называется нереоачей по ссылке. Второй параметр пере0ается по значению, то есть подпрограмме передается реальное количество элементов, и, а не адрес того места, где эта информация хранится. 2.9.3. Стековый фрейм На примере программы, представленной на рис. 2.26, давайте разберемся, как используется пространство стека. Во время выполнения подпрограммы применяемую ею информацию содержат шесть верхних элементов стека Эта область составляет собственное рабочее пространство подпрограммы, создаваемое при ее вызове и освобождаемое, когда управление возвращается вызывающей программе.
Она называется стпековым фрвхмом. Если для локальных переменных подпрограммы требуется дополнительное пространство, его также можно выделить в стеке. Пример типичного расположения информации в стековом фрейме приведен на рис. 2.27, В дополнение к указателю стека ЗР можно использовать еще один регистр, называемый указателем фрейма (Ргаше Ро1пФег, РР). Он облегчает доступ к параметрам подпрограммы и ее локальным переменным. Эти локальные переменные используются только внутри подпрограммы, так что память для их хранения удобнее всего выделить прямо в стековом фрейме, связанном с данной подпрограммой.
В нашем случае предполагается, что подпрограмма получает четыре параметра, применяет три локальные переменные и сохраняет содержимое регистров КО и К1, которые она использует для своих нужд. 102 Глава 2. Машинные команды и программы ЗР (указатель стека) Стековый фрейм для вызванной подпрограммы гр (указатель фрейма) м — — Старая вершина стека Рис.
2.27. Пример стекового фрейма Моче РР,-ЗР Мол е ЗР,РР Поскольку регистр РР указывает на область памяти, расположенную непосредственно над сохраненным в стеке адресом возврата, с его помощью легко обращаться к параметрам и локальным переменным, применяя индексный режим адресации.
Параметры адресуются так: 8(РР), 12(РР) и т. д., а локальные переменные так: -4(РР), -8(РР), .... Содержимое регистра РР в ходе выполнения подпрограммы остается неизменным, тогда как указатель стека ЗР должен всегда указывать на верхний элемент стека. Теперь давайте посмотрим, что происходит с указателями ЗР и РР при создании, использовании и уничтожении стекового фрейма в результате вызова конкретной подпрограммы. Мы будем считать, что перед вызовом подпрограммы ЗР указывает на старую вершину стека. Вызывающая программа помещает в стек четыре параметра.
Затем выполняется команда Са11, которая помещает в стек адрес возврата и передает управление подпрограмме. Теперь ЗР указывает на элемент стека„содержащий адрес возврата, и в следующий момент будет выполнена первая команда подпрограммы. Именно в это время указателю фрейма РР присваивается нужный адрес. Поскольку в качестве РР обычно выступает один их регистров общего назначения, он может содержать информацию, нужную вызывающей программе. Поэтому его содержимое тоже сохраняется в стеке.
А поскольку на вершину стека, которая будет началом стекового фрейма, указывает ЗР, содержимое данного регистра копируется в РР. Итак, первые две команды подпрограммы должны быть такими: 2.9. Подпрограммы 103 После их выполнения ЗР и РР указывают на сохраненное содержимое регистра РР. Далее в стеке выделяется пространство для трех локальных переменных, для чего выполняется команда ЗиЪггасс №12,8Р Напоследок в стеке сохраняется содержимое регистров процессора КО и К1. Теперь стековый фрейм сформирован и имеет такую структуру, как на рис.
2.27. Далее подпрограмма, выполнив свою непосредственную задачу, выталкивает ранее сохраненные значения регистров КО и К1 обратно в зти же регистры, удаляет из стекового фрейма локальные переменные с помощью команды АсЫ №12,8Р и выталкивает старое значение регистра РР обратно в этот регистр. Теперь ЗР указывает на адрес возврата и можно выполнить команду Кеспгп, возвращающую управление вызывающей программе. За удаление параметров из стекового фрейма отвечает вызывающая программа. Некоторые из таких параметров могут содержать возвращенные подпрограммой результаты вычислений. После того как это будет сделано, указатель стека должен указывать на исходную вершину стека; мы же вернемся к тому, с чего начинали.
Стековые фреймы для вложенных подпрограмм Стех — это структура данных, которая лучше всего подходит для хранения адресов возврата цепочки вложенных подпрограмм. Очевидно, что при вызове каждой из этих подпрограмм в стеке процессора формируется полный стековый фрейм.
В этой связи важно отметить, что сохраненное содержимое регистра ЕР в текущем фрейме на вершине стека — это указатель стекового фрейма той подпрограммы, которая вызвала текущую подпрограмму. В коде, приведенном на рис. 2.28, главная подпрограмма вызывает подпрограмму Я1В1, которая, в свою очередь, вызывает подпрограмму ЗПВ2.
Стековые фреймы этих двух вложенных подпрограмм изображены на рис. 2.29, Все их параметры передаются через стек. На рисунках показаны только поток выполнения подпрограмм и их данные — реализацию основных задач мы опустили. Порядок выполнения этой программы следующий. Главная программа помещает в стек два параметра, рагаш2 и рагаш1 (именно в таком порядке), а затем вызывает подпрограмму 8 ПВ1. Данная подпрограмма должна вычислить некоторое значение и передать его обратно главной программе через стек. В ходе вычислений ЗПВ1 вызывает вторую подпрограмму, Я1В2, выполняющую некоторую подзадачу.
Подпрограмма 811В1 передает подпрограмме Я1В2 один параметр, рагашЗ, и получает результат. После того как в Я1В2 будет выполнена команда Кегпгп, подпрограмма ВПВ1 сохранит этот результат в регистре К2. Затем БСВ1 продолжит свои вычисления, а закончив их, передаст ответ главной программе через стек. Когда управление будет возвращено главной программе, она сохранит полученный результат в памяти по адресу КЕБЫ и продолжит свою работу со следующей команды. Этот процесс достаточно подробно описан в комментариях на рис. 2.28.