Вызывающий абонент нажимает 5
, а затем 12
, затем адрес возврата, затем передает управление на sumsquare
, который использует формальный параметр a
в MP-3 (фактическое значение 5
) и b
в MP-2 (фактическое значение 12
) в стеке за обратным адресом в MP-1.При возврате из вызываемого в вызывающий объект адрес возврата удаляется из стека, оставляя фактические аргументы 5
и 12
в стеке, которые вызывающий затем выбрасывает из стека.
Существует как минимум триВозможные подходы:
Один из способов заключается в том, чтобы вызываемый объект (функция) переназначил первый формальный параметр по завершении функции, сохранив возвращаемое значение в формальном параметре a
в -3, а затемвызывающая сторона выталкивает только 2-й фактический аргумент из стека вместо обоих фактических аргументов, оставляя возвращаемое значение в стеке для обычного использования (т. е. путем вычисления выражения, например, арифметикой или присваиванием).Этот подход потребовал бы специальной обработки для функций с нулевым параметром.
Следующий подход должен был бы передать фиктивный параметр, резервирующий пространство для возвращаемого значения.Сначала будет передан фиктивный параметр, перед 5
и 12
.Вызываемый объект вместо сохранения возвращаемого значения в формальном параметре a
в -3, функция сохранит его в фиктивном в -4.Затем вызывающая сторона извлекает оба фактических аргумента 5
и 12
из стека, как в оригинале (но обычно использует пустышку, содержащую возвращаемое значение).Преимущество этого подхода состоит в том, что он является более регулярным (что позволяет функциям с нулевым параметром работать как все остальные).
Другой подход заключается в изменении соглашения о вызовах таким образом, чтобы вызываемый объект (функция) удалял свой собственный формальныйпараметры из стека, оставляя только возвращаемое значение в стеке.Для этого ему необходимо (1) сохранить возвращаемое значение в формальном параметре a
в -3, а затем (2) также переместить адрес возврата из его текущего местоположения в -1 в местоположение b
в -2, затем (3) вытаскивают старую копию адреса возврата из стека и возвращаются вызывающей стороне (выталкивают новую копию адреса возврата (aka b
) из стека, оставляя только возвращаемое значение)в стеке).В этом случае вызывающая сторона не извлекает фактические аргументы, как это делает вызываемый.Эта форма требует, чтобы функции выполняли небольшую работу в их конце, но экономит место на сайтах вызовов;это можно рационализировать, наблюдая, как правило, вызовов функций больше, чем самих функций (функции вызываются несколькими вызывающими).(Иногда специальная инструкция стека предоставляется, чтобы сделать это более напрямую.) Однако эта форма враждебна varargs ( variadic functions ) (и будет неработоспособна, если неизвестно, может ли какая-либо заданная функция быть variadic).*
Этот тип перестановки необходим для совместного использования одного стека как для оценки выражения, так и для связи функции.
В другой архитектуре два независимых стека позволили бы оставить возвращаемое значение в стеке выражениявсе еще будучи в состоянии отключить связь, чтобы вернуться к вызывающей стороне - хотя два стека добавили бы другие издержки аппаратному обеспечению.
И в еще одном архитектурном подходе был бы регистр или аккумулятор, и вот гдевозвращаемые значения пошли бы.