Вопрос по c++, function-calls, architecture, cpu-registers, call – C ++ (вложенные) инструкции вызова функций - регистры

3

ВC ++ FAQ:

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

относительно вызова вложенной функции

void f()
{
  int x = /*...*/;
  int y = /*...*/;
  int z = /*...*/;
  ...code that uses x, y and z...
  g(x, y, z);
  ...more code that uses x, y and z...
}

1 / Все ли реализации C ++ с регистрами и стеком? Означает ли это: реализация зависит от архитектуры компилятора / процессора / компьютера?

2 / Какова последовательность инструкций (без языка ассемблера, просто большая картинка), когда я звонюf() ? Я читал разные вещи по этой теме, а также я не помню, чтобы регистры упоминались, а только в стеке.

3 / какие дополнительные особенности / моменты следует подчеркнуть, когда вы имеете дело с вложенными функциями?

Спасибо

"что происходит, когда я вызываю f ()?" F () называется и поток идет туда, это на самом деле не ракетостроение Cat Plus Plus
я прояснил вопрос, я ищу рабочий процесс инструкций по вызову функции:) octoback
«Все ли реализации C ++ с регистрами и стеком?» Нет. R. Martinho Fernandes
«Вложенные функции»? Вы имеете в виду "вызовы функций"? Вызов функции не является чем-то особенным в C ++. На самом деле, это довольно распространенный способ программирования. Kerrek SB
Я имел в виду вызовы функций. да, это довольно распространенный вопрос об инструкциях / что происходит внутри, когда я вызываю функцию в C ++ (потому что есть возможность получить однозначный ответ на этот вопрос, и потому что я хотел бы знать, что конкретно для вложенных вызовов) octoback

Ваш Ответ

2   ответа
1

1. Хотя реализации регистра / стека являются наиболее распространенными базовыми реализациями компилятора C ++, ничто не мешает вам использовать другую архитектуру. Например, вы можете написать компилятор для генерации байт-кода Java или байт-кода .NET, и в этом случае у вас будет стековый компилятор C ++.

2. Когда вы вызываете f (), типичный подход:

Вставьте адрес возврата в стек и перейдите к f ()

В ф ():

Выделите место для локалей x, y и z. Обычно это делается в стеке. Взгляни наэта статья на стеки вызовов.

Когда вы доберетесь до g (x, y, z), компилятор сгенерирует код для помещения значений в стек, получая доступ к их значениям в кадре стека функции f (). Обратите внимание, что C / C ++ изменяет параметры справа налево.

Когда вы дойдете до конца f (), компилятор вставляетreturn инструкции. У вершины стека есть адрес для возврата (он был передан до вызова f ())

3. Во вложенных функциях нет ничего особенного, так как все соответствует одному базовому шаблону:

Для вызова функции - нажмите параметры и вызовите функцию.Внутри функции - выделить место для локальных переменных в стеке

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

ПРИМЕЧАНИЕ. Хотя передача параметров стеком, безусловно, является наиболее распространенным подходом, существуют и другие. Взгляните на эту статью назарегистрировать окна если вы заинтересованы в том, чтобы узнать больше.

3

2 это зависит от многих вещей, включая компилятор и платформу. В основном называются разные способы передачи и возврата аргументов в функциисоглашения о вызовах, статьяСоглашения о вызовах на платформе x86 подробно расскажем о последовательности операций, и вы сможете увидеть, насколько уродливым и сложным он становится с этой небольшой комбинацией платформ и компиляторов, поэтому, скорее всего, вы слышали всевозможные сценарии,Ген на соглашениях о вызовах функций. охватывает более широкий набор сценариев, включая64 bit платформы, но труднее читать. Это становится еще сложнее, потому чтоgcc не может на самом делеpush а такжеpop стек, но непосредственно манипулировать указателем стека, мы можем увидеть пример этого, хотя и в сборкеВот, Трудно обобщить соглашения о вызовах, если число аргументов достаточно мало, многие соглашения о вызовах могут избежать использованияstack на все и буду использоватьregisters исключительно.

Что касается числа3Вложенные функции ничего не меняют, они просто повторяют процедуру снова для следующего вызова функции.

Что касается числа1 Как указал Шон.Net компилирует в байтовый код с выполняет все свои операции в стеке. Страница Википедии наОбщий промежуточный язык есть хороший пример.

x86-64 ABI документ Это еще один отличный документ, если вы хотите понять, как работает конкретное соглашение о вызовах.Figure 3.5 and 3.6 аккуратны, так как они дают хороший пример функции с множеством параметров и того, как каждый параметр передается с использованием комбинацииgeneral purpose registers, floating point registers иstack, Такая симпатичная диаграмма - редкая находка при просмотре документов, которые охватывают соглашения о вызовах.

Похожие вопросы