Стек вызовов

Материал из Википедии — свободной энциклопедии
Перейти к: навигация, поиск

Стек вызовов (применительно к процессорам — просто «стек») — хранит информацию для возврата управления из процедур в программу (или подпрограмму, при вложенных или рекурсивных вызовах) и/или для возврата в программу из обработчика прерывания. В том числе при переключении задач в многозадачной среде.

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

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

Реализация[править | править вики-текст]

Стек вызовов может быть реализован как в виде специализированного стекового регистра ограниченной глубины (или даже обычного регистра адреса возврата, например в некоторых моделях PowerPC), так и в виде указателя вершины стека в оперативную память или регистровый файл процессора.[1]

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

Поддержка[править | править вики-текст]

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

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

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

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

Использование[править | править вики-текст]

Типичный случай использование стека языком высокого уровня на примере вызова процедуры с аргументами «A, B, C» (с соглашениями вызова Паскаля) в сравнении с языком ассемблера

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

Кроме адресов возврата в стеке могут сохраняться другие данные, например:

Использование стека в многозадачных системах[править | править вики-текст]

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

Нестандартное использование[править | править вики-текст]

Стек может быть использован нестандартно, например:

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

Альтернативное использование[править | править вики-текст]

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

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

Замечания[править | править вики-текст]

  • Императивные языки программирования высокого уровня, как правило, не имеют возможностей явного оперирования стеком вызовов, но есть и исключения. Например, в Forth есть прямой доступ к системному стеку вызовов (под названием «стека возвратов», в отличие от «стека данных» этого языка).

См. также[править | править вики-текст]

Примечания[править | править вики-текст]