Для чего используется ключевое слово fastcall в visual c?

StackOverflow https://stackoverflow.com//questions/10671281

Вопрос

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

Это было полезно?

Решение

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

Существует множество различных соглашений о вызовах, наиболее популярными из которых являются stdcall и cdecl.

Вы можете подумать, что есть только один способ сделать это, но на самом деле существуют десятки способов вызвать функцию и передавать переменные внутрь и наружу.Вы могли бы поместить входные параметры в стек (push, push, push для вызова;хлоп, хлоп, хлоп для считывания входных параметров).Или, возможно, вы предпочли бы поместить их в регистры (это fastcall - он пытается подогнать некоторые входные параметры в регистры для ускорения).

Но тогда как насчет заказа?Вы двигаете их слева направо или справа налево?Как насчет результата - всегда есть только один (при условии отсутствия ссылочных параметров), так помещаете ли вы результат в стек, в регистр, по определенному адресу памяти?

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

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

Самым популярным соглашением о вызове (на сегодняшний день) является cdecl, которое является стандартным соглашением о вызове как в C, так и в C++.WIN32 API использует stdcall, что означает, что любой код, вызывающий WIN32 API, должен использовать stdcall для этих вызовов функций (что делает его еще одним популярным выбором).

fastcall это немного странно - люди поняли, что для многих функций только с одним параметром ввода / вывода нажатие и извлечение из стека, основанного на памяти, требует довольно больших накладных расходов и делает вызовы функций немного тяжелыми, поэтому разные компиляторы ввели (разные) соглашения о вызовах, которые будут размещать один или несколько параметров в регистрах перед помещением остальных в стек для повышения производительности.Проблема в том, что не все компиляторы использовали одни и те же правила для определения того, что куда идет и кто что делает с fastcall, и в результате вы должны быть осторожны при его использовании, потому что вы никогда не будете знать, кто что делает.Наконец, смотрите Действительно ли fastcall быстрее? для получения информации о fastcall преимущества в производительности.

Сложная штука.

Что-то важное, о чем нужно помнить:не добавляйте и не изменяйте соглашения о вызовах, если вы не знаете именно так что вы делаете, потому что, если и вызывающий, и вызываемый объект не согласны с соглашением о вызове, вы, скорее всего, столкнетесь с повреждением стека и ошибкой сегмента.Обычно это происходит, когда у вас есть функция, вызываемая в DLL/разделяемой библиотеке, и написана программа, которая зависит от того, что DLL/SO/dylib является определенным соглашением о вызове (скажем, cdecl), затем библиотека перекомпилируется с другим соглашением о вызове (скажем, fastcall).Теперь старая программа больше не может взаимодействовать с новой библиотекой.

Другие советы

Википедия утверждает, что

Соглашения, озаглавленные fastcall, не были стандартизированы и были реализованы по-разному, в зависимости от поставщика компилятора.Обычно соглашения о вызове fastcall передают один или несколько аргументов в регистрах, что уменьшает количество обращений к памяти, необходимых для вызова.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top