Обычно существует комбинация набора команд процессоров и соглашения о вызовах, которое использует компилятор. Некоторые процессоры возвращают только с использованием адресов в стеке, другие могут использовать адреса только в других регистрах, а некоторые могут решать только программисты. Естественно, вы могли бы, если хотите, вывести адрес стека для регистрации только для процессора типа ветви или поместить адрес в стек из регистра для процессора только для стека.
В ваших старых проектах, таких как x86, обычно инструкция вызова помещает адрес возврата в стек, а инструкция возврата извлекает адрес возврата из стека, чтобы использовать его. С x86 CS также может быть в стеке. Процессоры в этой категории часто помещают флаги в стек для прерывания, а при возврате из прерывания всплывают флаги и адрес возврата.
На основе правил процессора, которые вы выбираете, как вы возвращаетесь из функции, создается соглашение, так что все функции используют одни и те же правила, а компилятор использует это соглашение.
Вам нужно немного лучше понять процессор, который вы используете, и соглашение о вызовах, которое вы пытаетесь использовать или использовать.