Конституция Армении: Статья 18.1
Конституция Армении (Статья 18.1) закрепляет «исключительную миссию Армянской Апостольской Святой Церкви как национальной церкви в духовной жизни армянского народа, в деле развития его национальной культуры и сохранения его национальной самобытности»:
Соглашение о вызове

Соглашение о вызове

Материал из Википедии — свободной энциклопедии

Соглашение о вызове (англ. calling convention) — описание технических особенностей вызова подпрограмм, определяющее:

  • способы передачи параметров подпрограммам;
  • способы вызова (передачи управления) подпрограмм;
  • способы передачи результатов вычислений, выполненных подпрограммами, в точку вызова;
  • способы возврата (передачи управления) из подпрограмм в точку вызова.

Является частью двоичного интерфейса приложений (англ. application binary interface, ABI).

Состав

Соглашение о вызове описывает следующее:

  • способ передачи аргументов в функцию. Варианты:
    • аргументы передаются через регистрыпроцессора;
    • аргументы передаются через стек;
    • смешанные (соответственно, стандартизируется алгоритм, определяющий, что передаётся через регистры, а что — через стек или другую память):
      • первые несколько аргументов передаются через регистры; остальные — через стек (небольшие аргументы[1]) или другую память (большие аргументы[2]);
      • аргументы небольшого размера[1] передаются через стек, большие аргументы[2] — через другую память;
  • порядок размещения аргументов в регистрах и/или стеке. Варианты:
    • слева направо или прямой порядок: аргументы размещаются в том же порядке, в котором они перечислены при вызове функции. Достоинство: машинный код соответствует коду на языке высокого уровня;
    • справа налево или обратный порядок: аргументы передаются в порядке от конца к началу. Достоинство: упрощается реализация функций, принимающих произвольное число аргументов (например, printf()) (так как на вершине стека оказывается всегда первый аргумент);
  • код, ответственный за очистку стека:
    • код, вызывающий функцию, или вызывающая программа. Достоинство: возможность передачи в функцию произвольного числа аргументов;
    • код самой функции или вызываемая функция. Достоинство: уменьшение количества инструкций, необходимых для вызова функции (инструкция для очистки стека записывается в конце кода функции и только один раз);
  • конкретные инструкции, используемые для вызова и возврата. Для процессораx86, работающего в защищённом режиме, используются исключительно инструкцииcall и ret; при работе в стандартном режиме используются инструкцииcall near, call far и pushf/call far (для возврата соответственно retn, retf и iret);
  • способ передачи в функциюуказателя на текущий объект (this или self) в объектно-ориентированныхязыках. Варианты (для процессора x86, работающего в защищённом режиме):
    • как первый аргумент;
    • через регистрecx или rcx;
  • кто отвечает за сохранение/восстановление того или иного регистра процессора: вызывающая программа или вызываемая функция.

Соглашение о вызове может быть описано в документации к ABI архитектуры, в документации к ОС или в документации к компилятору.

Использование

Соглашения о вызовах, используемые на 32-битном x86

Список неполный, представлены основные из применяемых по сей день соглашений.

Для перечисленных ниже соглашений (кроме cdecl) перед возвратом значений из функции подпрограмма обязана восстановить значения сегментныхрегистров, регистровesp и ebp. Сохранением-восстановлением остальных регистров занимается вызывающая программа.

Если размер возвращаемого значения функции не больше размера регистраeax, возвращаемое значение сохраняется в регистреeax. Иначе возвращаемое значение сохраняется на вершине стека, а указатель на вершину стека сохраняется в регистреeax. Если возвращается объект с автодеструктором (любой объект C++ с ненулевым деструктором, строки произвольной длины в Паскале, BSTR в WinAPI и т. д.), вызывающая программа должна корректно уничтожить его.

cdecl

cdecl (сокращение от англ. c-declaration) — соглашение о вызовах, используемое компиляторами для языкаСи (отсюда название).

Аргументы функций передаются через стек, справа налево. Аргументы, размер которых меньше 4 байт, расширяются до 4 байт. За сохранение регистров EAX, ECX, EDX и стека сопроцессора отвечает вызывающая программа, за остальные — вызываемая функция. Очистку стека производит вызывающая функция. Это основной способ вызова функций с переменным числом аргументов (например, printf()). Способы получения возвращаемого значения функции приведены в таблице.

Перед вызовом функции вставляется код, называемый прологом (англ. prolog) и выполняющий следующие действия:

После вызова функции вставляется код, называемый эпилогом (англ. epilog) и выполняющий следующие действия:

pascal

pascal — соглашение о вызовах, используемое компиляторами для языкаПаскаль. Также применялось в ОСWindows 3.x.

Аргументы процедур и функций передаются через стек, слева направо. Указатель на вершину стека (значение регистраesp) на исходную позицию возвращает вызываемая подпрограмма. Изменяемые параметры передаются только по ссылке. Возвращаемое значение передаётся через изменяемый параметр Result. Параметр Result создаётся неявно и является первым аргументом функции.

stdcall или winapi

stdcall или winapi — соглашение о вызовах, применяемое в ОСWindows для вызова функцийWinAPI.

Аргументы функций передаются через стек, справа налево. Очистку стека производит вызываемая подпрограмма.

fastcall

fastcall — общее название соглашений, передающих параметры через регистры (обычно это самый быстрый для выполнения компьютером способ, отсюда и название — «быстрый вызов». Если для вызова регистров недостаточно, то дополнительно используется стек.

Соглашение о вызовах fastcall не стандартизировано, поэтому используется только для вызова процедур и функций, не экспортируемых из исполняемого модуля и не импортируемых извне.

В компиляторах фирмы Borland для соглашения __fastcall, называемого также register[5], параметры передаются слева направо в регистрахeax, edx и ecx и, если параметров больше трёх, в стеке, также слева направо. Исходное значение указателя на вершину стека (значение регистраesp) возвращает вызываемая подпрограмма.

В 32-разрядной версии компилятора фирмы Microsoft[6], а также в компилятореGCC[7], соглашение __fastcall, также называемое __msfastcall, определяет передачу первых двух параметров слева направо в регистрахecx и edx, а остальные параметры передаются справа налево в стеке. Очистку стека производит вызываемая подпрограмма.

safecall

safecall — соглашение о вызовах, используемое в Delphi и Free Pascal для взаимодействия с интерфейсами COM. При вызове из COM возникающие в функцииисключения перехватываются и возвращаются как коды ошибок HRESULT в соответствии с правилами COM/OLE. При вызове COM функций возвращаемые ими соответствующие ошибкам коды HRESULT транслируются в исключения.

Возвращаемое значение safecall функции передаётся как дополнительный последний аргумент на стеке по ссылке. В остальном конвенция safecall соответствует конвенции stdcall.

// safecallfunction DoSomething ( a : DWORD ) : DWORD; safecall;// аналог stdcall, без трансляции исключенийfunction DoSomething ( a : DWORD ; out Result : DWORD ) : HResult; stdcall;

thiscall

thiscall — соглашение о вызовах, используемое компиляторами для языкаC++ при вызове методов классов в объектно-ориентированном программировании.

Аргументы функции передаются через стек, справа налево. Очистку стека производит вызываемая функция. Соглашение thiscall отличается от stdcall соглашения только тем, что указатель на объект, для которого вызывается метод (указательthis), записывается в регистрecx[8].

См. также

  • libffi[англ.] — библиотека для FFI с набором различных соглашений.

Примечания

  1. 12Под небольшими аргументами понимаются значения, размер которых меньше или равен размеру регистрапроцессора. Например, 1, 2 и 4 байта для процессора x86, работающего в 32-битном режиме.
  2. 12Под большими аргументами понимаются значения, размер которых больше размера регистрапроцессора. Например, 8 и более байт для процессора x86, работающего в 32-битном режиме.
  3. Пролог (англ. prologue) — код, выполняющий сохранение регистров, передачу аргументов в функцию, размещение локальных переменных в стеке функции.
  4. Эпилог (англ. epilogue) — код, выполняющий возврат управления вызывающей функции, очистку стека, восстановление значений регистров, передачу возвращаемого значения функции.
  5. Program Control: Register Convention. docwiki.embarcadero.com (1 июня 2010). Дата обращения: 27 сентября 2010. Архивировано 20 ноября 2012 года.
  6. _fastcall. msdn.microsoft.com. Дата обращения: 27 сентября 2010. Архивировано 20 ноября 2012 года.
  7. Ohse, Uwe. gcc attribute overview: function fastcall. ohse.de. Дата обращения: 27 сентября 2010. Архивировано 20 ноября 2012 года.
  8. thiscall (C++) (англ.). msdn.microsoft.com.

Ссылки

ТипРазмер возвращаемого значения, байтСпособ передачи возвращаемого значения Примечание
Целое число 1 Через регистрal
Целое число 2 Через регистрax
Целое число, указатель4 Через регистрeax
Целое число 8 Через пару регистровedx:eax
Число с плавающей запятой4, 8, 10 Через регистрst0 (из псевдостека x87, FPU)
Другие Больше 8 Указатель на значение в регистреeaxУказатель на выделенную под возвращаемое значение память передаётся нулевым аргументом в функцию и возвращается в регистреeax