Общие сведения о соглашениях о вызовах для архитектуры x64
Обновлен: Ноябрь 2007
Двумя важнейшими различиями между архитектурами x86 и x64 является возможность 64-битной адресации и набор из 16 64-битных регистров общего назначения. Предоставляя расширенный набор регистров, x64 использует только соглашение о вызовах __fastcall и модель RISC-архитектуры обработки исключений. Модель соглашения о вызовах __fastcall использует регистры для первых четырех аргументов, а для передачи других параметров используется кадр стека.
Следующий параметр компилятора позволяет оптимизировать приложение для x64:
Соглашение о вызовах
Машинный интерфейс для приложений Application Binary Interface (ABI) x64 — это 4 регистра соглашения о вызовах с возможностью последующего возвращения этих регистров в стек. Существует точное однозначное соответствие между аргументами в функции и регистрами для этих аргументов. Любые аргументы, не равные 8 байтам или 1, 2, 4 или 8 байтам, передаются по ссылке. Попыток разместить один аргумент по нескольким регистрам не происходит. Регистровый стек x87 не используется. Его можно использовать, но он должен быть временным при вызове функций. Все операции с плавающей запятой выполняются с помощью 16 регистров XMM. Аргументы передаются в регистрах RCX, RDX, R8 и R9. Если аргументы являются типами float или double, они передаются в регистрах XMM0L, XMM1L, XMM2L и XMM3L. 16-байтовые аргументы передаются по ссылке. Передача параметров подробно описана в разделе Передача параметров. Регистры RAX, R10, R11, XMM4 и XMM5 являются энергозависимыми. Все остальные регистры являются энергонезависимыми. Использование регистров подробно описано в разделах Использование регистров и Сохраняемые регистры вызываемого и вызывающего объектов.
Вызывающая функция отвечает за выделение пространства для параметров вызываемой функции и должна всегда выделять достаточное пространство для 4 параметров, даже если вызываемая функция не содержит такого количества параметров. Это помогает упростить поддержку функций без прототипов и функций с переменным количеством аргументов (vararg) C/C++. Для функций с переменным количеством аргументов или для функций без прототипов любое значение типа float должно быть продублировано в соответствующем регистре общего назначения. Любые параметры, следующие после первых 4, до вызова должны сохраняться в стеке над резервным хранилищем для первых четырех. Сведения о функции с переменным количеством аргументов представлены в разделе Функции с переменным количеством аргументов (Varargs). Сведения о функции без прототипов представлены в разделе Функции без прототипа.
Выравнивание
Большинство структур выровнены естественным выравниванием. Главными исключениями являются указатели стека и функции распределения памяти malloc или alloca, которые выровнены на 16 байт для сохранения производительности. Выравнивание свыше 16 байт должно выполняться вручную, но начиная с 16 байт выполняется общее выравнивание размера для операций XMM, которого должно хватать для большей части кода. Дополнительные сведения о структуре и выравнивании см. в разделе Типы и хранилище. Дополнительные сведения о стеке см. в разделе Использование стека.
Способность очищаться
Все неконечные функции (функции, которые никогда не вызывают функцию, а также никогда не выделяют пространство стека) должны дополняться данными (относится к типам данных xdata или ehdata, на которые есть указатель из pdata), которые объясняют ОС, каким образом выполнять их очищение для сохранения неизменяемых регистров. Прологи и эпилоги строго ограничены, следовательно, они могут быть правильно описаны в xdata. Указатель стека должен быть выровнен на 16 байт, за исключением конечных функций, в любой области кода, которая не является частью эпилога или пролога. Дополнительные сведения о структуре функции пролога и эпилога см. в разделе Пролог и эпилог. Дополнительные сведения об обработке исключений и обработке исключений/очистке pdata и xdata см. в разделе Обработка исключений (x64).