Как процессор получает обратный адрес из стека

#stack #procedure #machine-language

#стек #процедура #машинный код

Вопрос:

Как процессор получает обратный адрес из стека, который передается вызывающей функцией. откуда он знает, что это обратный адрес, а не что-то еще?

Комментарии:

1. «откуда он знает, что это обратный адрес, а не что-то еще?» Он не знает. Если это что-то другое, оно перейдет на какой-то неправильный адрес памяти и произойдет сбой.

2. Итак, какой механизм мы используем для возврата к правильному адресу?

3. Я просто думаю об одном и том же вопросе, и ответ @tkausl не помогает — сформулировать вопрос немного иначе: «почему процессор использует это значение в качестве адреса перехода, а другие значения не используются в качестве адресов перехода?». Может быть, взгляд на assember дает ответ? Инструкции должны перед возвратом функции извлечь все переменные стека из стека. И затем следующий элемент в стеке — это адрес возврата.

4. @radix сам процессор понятия не имеет, что представляет собой значение в стеке. Он просто извлекает значение из стека и переходит на этот адрес. Компилятор (или программист, если программа написана на ассемблере) должен убедиться, что все переданные значения извлекаются перед возвратом.

Ответ №1:

Мне пришлось его искать, но это достаточно объяснено в Википедии

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

Обратный адрес — это, например, сама запись в стеке после того, как были извлечены локальные переменные от вызываемого абонента (по крайней мере, в примере Википедии — могут быть различия в разных архитектурах).

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

Я не знаю, несет ли вызываемый абонент ответственность за удаление параметров, которые были переданы от вызывающего абонента — это может зависеть от архитектуры.

Обновление: пример сборки

В конце функции (вызываемого объекта) переменные, которые были сохранены в стеке (т. Е. Некоторые значения регистров и адрес возврата вызывающему объекту), возвращаются обратно в соответствующие регистры:

 pop    {r4, r5, r6, pc}
  

В ARM это приводит к тому, что четыре следующих слова из стека попадают в эти регистры.
Один из них — это обратный адрес, который отображается в $ PC (счетчик программ).
Таким образом, выполнение продолжается с инструкцией по обратному адресу, который отображается в $ PC.

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