Раставицкое соглашение
- 1 year ago
- 0
- 0
Соглашение о вызове ( англ. calling convention) — описание технических особенностей вызова подпрограмм , определяющее:
Является частью двоичного интерфейса приложений ( англ. application binary interface , ABI).
Соглашение о вызове описывает следующее:
printf()
) (так как на вершине стека оказывается всегда первый аргумент);
call
и
ret
; при работе в стандартном режиме используются
инструкции
call near
,
call far
и
pushf/call far
(для возврата соответственно
retn
,
retf
и
iret
);
this
или
self
) в
объектно-ориентированных
языках
. Варианты (для процессора
x86
, работающего в
защищённом режиме
):
ecx
или
rcx
;
Соглашение о вызове может быть описано в документации к ABI архитектуры, в документации к ОС или в документации к компилятору .
Для перечисленных ниже соглашений (кроме
) перед возвратом значений из
функции
подпрограмма обязана восстановить значения
сегментных
регистров
,
регистров
esp
и
ebp
. Значения остальных
регистров
могут не восстанавливаться.
Если размер возвращаемого значения
функции
не больше
размера регистра
eax
, возвращаемое значение сохраняется в
регистре
eax
. Иначе возвращаемое значение сохраняется на вершине стека, а
указатель
на вершину стека сохраняется в
регистре
eax
. Если возвращается объект с автодеструктором (любой объект C++ с ненулевым
деструктором
, строки произвольной длины в Паскале, BSTR в
WinAPI
и т. д.), вызывающая программа должна корректно уничтожить его.
cdecl
(сокращение от
англ.
c
-
declaration
) — соглашение о вызовах, используемое
компиляторами
для
языка
Си
(отсюда название).
Аргументы
функций
передаются через стек, справа налево. Аргументы, размер которых меньше 4 байт, расширяются до 4 байт. Очистку стека производит . Это основной способ вызова
функций
с переменным числом аргументов (например,
printf()
). Способы получения возвращаемого значения функции приведены в таблице.
Тип | Размер возвращаемого значения, байт | Способ передачи возвращаемого значения | Примечание |
---|---|---|---|
Целое число, указатель | 1, 2, 4 |
Через
регистр
eax
|
Значения, размер которых меньше 4 байт, расширяются до 4 байт |
Целое число | 8 |
Через пару
регистров
edx:eax
|
|
Число с плавающей точкой | 4, 8 |
Через
регистр
st0
(из псевдостека
x87
,
FPU
)
|
|
Другие | Больше 8 |
Через
регистр
eax
|
Указатель
на
структуру данных
сохраняется в
регистре
eax
|
Перед вызовом функции вставляется код , называемый прологом ( англ. prolog) и выполняющий следующие действия:
После вызова функции вставляется код , называемый эпилогом ( англ. epilog) и выполняющий следующие действия:
pascal
— соглашение о вызовах, используемое
компиляторами
для
языка
Паскаль
. Также применялось в
ОС
Windows 3.x
.
Аргументы процедур и функций передаются через стек, слева направо. Указатель на вершину стека (значение
регистра
esp
) на исходную позицию возвращает
. Изменяемые параметры передаются только по
ссылке
. Возвращаемое значение передаётся через изменяемый параметр Result. Параметр Result создаётся неявно и является первым аргументом
функции
.
stdcall
или
winapi
— соглашение о вызовах, применяемое в
ОС
Windows
для вызова
функций
WinAPI
.
Аргументы функций передаются через стек, справа налево. Очистку стека производит .
fastcall
— общее название соглашений, передающих параметры через
регистры
(обычно это
самый быстрый
для выполнения компьютером способ, отсюда и название (здесь приставка «
fast
» с
англ.
переводится как «
быстрый
», а «
call
» с
англ.
переводится как «
вызов
». То есть, дословно переводится как «
быстрый вызов
»)). Если для сохранения всех параметров и промежуточных результатов — регистров недостаточно, то дополнительно используется стек.
Соглашение о вызовах
fastcall
не стандартизировано, поэтому используется только для вызова процедур и функций, не экспортируемых из
исполняемого модуля
и не импортируемых извне.
В
компиляторах
фирмы
Borland
для соглашения
__fastcall
, называемого также
register
, параметры передаются
слева направо
в
регистрах
eax
,
edx
и
ecx
и, если параметров больше трёх, в стеке, также
слева направо
. Исходное значение указателя на вершину стека (значение
регистра
esp
) возвращает .
В 32-разрядной версии
компилятора
фирмы
Microsoft
, а также в
компиляторе
GCC
, соглашение
__fastcall
, также называемое
__msfastcall
, определяет передачу первых двух параметров
слева направо
в
регистрах
ecx
и
edx
, а остальные параметры передаются
справа налево
в стеке. Очистку стека производит .
safecall
— соглашение о вызовах, используемое для вызова методов интерфейсов
COM
.
Методы интерфейсов COM представляют собой функции , возвращающие тип HRESULT. Код , добавляемый после вызова функции , анализирует возвращаемое значение. При наличии ошибки код записывает код ошибки, сообщение об ошибке и поднимает исключение . Иначе настоящее возвращаемое значение скрывается, вместо него используется параметр, передаваемый в функцию последним по ссылке. Например, можно считать два следующих объявления функции эквивалентными.
// safecall function DoSomething (a : DWORD) : DWORD ; safecall ; // симуляция safecall function DoSomething (a : DWORD ; out Result : DWORD) : HResult ; stdcall ;
thiscall
— соглашение о вызовах, используемое
компиляторами
для
языка
C++
при вызове методов
классов
в
объектно-ориентированном программировании
.
Аргументы
функции
передаются через стек, справа налево. Очистку стека производит
вызываемая
функция. Соглашение
thiscall
отличается от
stdcall
соглашения только тем, что
указатель
на объект, для которого вызывается метод (
указатель
this
), записывается в
регистр
ecx
.