Общие сведения о соглашениях о вызовах для архитектуры x64
Двумя важнейшими различиями между архитектурами 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).