#stack #procedure #machine-language
#стек #процедура #машинный код
Вопрос:
Как процессор получает обратный адрес из стека, который передается вызывающей функцией. откуда он знает, что это обратный адрес, а не что-то еще?
Комментарии:
1. «откуда он знает, что это обратный адрес, а не что-то еще?» Он не знает. Если это что-то другое, оно перейдет на какой-то неправильный адрес памяти и произойдет сбой.
2. Итак, какой механизм мы используем для возврата к правильному адресу?
3. Я просто думаю об одном и том же вопросе, и ответ @tkausl не помогает — сформулировать вопрос немного иначе: «почему процессор использует это значение в качестве адреса перехода, а другие значения не используются в качестве адресов перехода?». Может быть, взгляд на assember дает ответ? Инструкции должны перед возвратом функции извлечь все переменные стека из стека. И затем следующий элемент в стеке — это адрес возврата.
4. @radix сам процессор понятия не имеет, что представляет собой значение в стеке. Он просто извлекает значение из стека и переходит на этот адрес. Компилятор (или программист, если программа написана на ассемблере) должен убедиться, что все переданные значения извлекаются перед возвратом.
Ответ №1:
Мне пришлось его искать, но это достаточно объяснено в Википедии
Таким образом, вызываемый объект (вызываемая подпрограмма) сам отвечает за извлечение всего из стека (собственных локальных переменных) и выполнение перехода к обратному адресу, предоставленному вызывающей функцией.
Обратный адрес — это, например, сама запись в стеке после того, как были извлечены локальные переменные от вызываемого абонента (по крайней мере, в примере Википедии — могут быть различия в разных архитектурах).
Указатель кадра будет подсказкой для местоположения обратного адреса, но может быть опущен для повышения производительности, поэтому вы не можете на это полагаться.
Я не знаю, несет ли вызываемый абонент ответственность за удаление параметров, которые были переданы от вызывающего абонента — это может зависеть от архитектуры.
Обновление: пример сборки
В конце функции (вызываемого объекта) переменные, которые были сохранены в стеке (т. Е. Некоторые значения регистров и адрес возврата вызывающему объекту), возвращаются обратно в соответствующие регистры:
pop {r4, r5, r6, pc}
В ARM это приводит к тому, что четыре следующих слова из стека попадают в эти регистры.
Один из них — это обратный адрес, который отображается в $ PC (счетчик программ).
Таким образом, выполнение продолжается с инструкцией по обратному адресу, который отображается в $ PC.
Я не могу точно сказать, как работает регистр ссылок. Предполагается, что он должен содержать адрес возврата (но для вызовов вложенных функций, конечно, нам все равно нужен стек для хранения нескольких адресов возврата).