12-10-2023
Соглашение вызова или модель вызова (англ. Calling convention) — часть двоичного интерфейса приложений, которая регламентирует технические особенности вызова подпрограммы, передачи параметров, возврата из подпрограммы и передачи результата вычислений в точку вызова.
Содержание |
Соглашение вызова определяет следующие особенности процесса использования подпрограмм:
call near
, call far
и pushf/call far
(для возврата применяются соответственно retn
, retf
, iret
).Соглашения вызова зависят от архитектуры целевой машины и компилятора.
Во всех нижеперечисленных соглашениях(кроме cdecl) подпрограмма обязана обеспечить восстановление перед возвратом значений сегментных регистров процессора, а также регистров ESP
и EBP
. Значения остальных могут не восстанавливаться. Возвращаемое значение функции хранится в регистре eax
. Если его размер слишком велик для размещения в регистре, то оно размещается на верхушке стека, а значение в регистре eax
будет указывать на него.
Основной способ вызова для Си (отсюда название, сокращение от «c-declaration»). Аргументы передаются через стек, справа налево. Очистку стека производит вызывающая программа. Это основной способ вызова функций с переменным числом аргументов (например, printf(…))
Основной способ вызова для Паскаля, также применялся в Windows 3.x. Аргументы передаются через стек, слева направо. Указатель стека на исходную позицию возвращает подпрограмма. Причём, изменяемые параметры передаются только по ссылке, а у функций неявно создаётся дополнительный первый изменяемый параметр Result, через который и возвращается значение.
Применяется при вызове функций WinAPI. Аргументы передаются через стек, справа налево. Очистку стека производит вызываемая подпрограмма.
Передача параметров через регистры, обычно самая быстрая; если все параметры и промежуточные результаты умещаются в регистрах, манипуляции со стеком вообще не нужны. Fastcall не стандартизирован, поэтому используется только в функциях, которые программа не экспортирует наружу. Например, у Borland параметры передаются слева направо в eax
, edx
, ecx
и, если параметров больше трёх, в стеке. Указатель стека на исходное значение возвращает подпрограмма.
Fastcall Borland применяется по умолчанию в Delphi.
Для x64 целей компилятор Microsoft VisualStudio 2010 CL принимает данное соглашение по умолчанию, остальные игнорируются, даже если заданы явно. Передача параметров в данном случае происходит при помощи 4х 64х разрядных регистра: rcx, rdx, r8, r9
. В случае если параметров больше — остальные передаются через стек.
Обеспечивает более удобный для использования в распространённых языках высокого уровня способ вызова методов интерфейсов при использовании модели COM.
Все методы интерфейсов COM представляют собой функции, возвращающие код завершения типа HRESULT, который должен анализироваться в месте вызова. Как правило, это не вполне удобно: большинство используемых с этой технологией языков имеют механизмы обработки исключений, и в них удобнее использовать обычные вызовы функций и процедур, возвращающие прикладные значения, а для обработки ошибок применять исключения. Именно такую возможность предоставляет safecall.
Можно считать, что вызов
function DoSomething(a: DWORD): DWORD; safecall;
в действительности представляет собой вызов
function DoSomething(a: DWORD; out Result: DWORD): HResult; stdcall;
причём организованный таким образом, что если возвращённое значение типа HRESULT будет содержать флаг ошибки, то в результате вызова будет сгенерировано исключение с кодом и текстом, соответствующим обнаруженной ошибке.
Используется в компиляторах C++. Обеспечивает передачу аргументов при вызовах методов класса в объектно ориентированной среде. Аргументы передаются через стек, справа налево. Очистку стека производит вызываемая функция, то есть тот же самый stdcall. Указатель (this) на объект, для которого вызывается метод, записывается в регистр ECX [1].
Соглашение вызова.