Программные соглашения для 64-разрядных системx64 software conventions

В этом разделе описывается методология соглашения о вызовах в C++ для x64, 64-разрядного расширения архитектуры x86.This section describes the C++ calling convention methodology for x64, the 64-bit extension to the x86 architecture.

Общие сведения о соглашениях о вызовах для архитектуры x64Overview of x64 calling conventions

Двумя важными различиями между архитектурами x86 и x64 являются возможность 64-разрядной адресации и неструктурированный набор из 16 64-разрядных регистров общего назначения.Two important differences between x86 and x64 are the 64-bit addressing capability and a flat set of 16 64-bit registers for general use. Учитывая расширенный набор регистров, архитектура x64 использует соглашение о вызовах __fastcall и модель обработки исключений на основе RISC.Given the expanded register set, x64 uses the __fastcall calling convention and a RISC-based exception-handling model. Соглашение __fastcall использует регистры для первых четырех аргументов и кадр стека для передачи дополнительных аргументов.The __fastcall convention uses registers for the first four arguments and the stack frame to pass additional arguments. Подробные сведения о соглашении о вызовах x64, в том числе об использовании регистров, параметрах стека, возвращаемых значениях и раскрутке стека, см. в статье Соглашение о вызовах x64.For details on the x64 calling convention, including register usage, stack parameters, return values, and stack unwinding, see x64 calling convention.

Включение оптимизации для x64Enable optimization for x64

Следующий параметр компилятора позволяет оптимизировать приложение для архитектуры x64:The following compiler option helps you optimize your application for x64:

Типы данных и их хранениеTypes and storage

В этом разделе перечисляются типы данных в архитектуре x64 и занимаемое ими место.This section describes the enumeration and storage of data types for the x64 architecture.

Скалярные типыScalar types

Несмотря на возможность доступа к данным с любым выравниванием, рекомендуется выравнивать данные по естественной границе или кратной ей границе, чтобы избежать снижения производительности.Although it's possible to access data with any alignment, it's recommended to align data on its natural boundary, or some multiple, to avoid performance loss. Перечисления — это целочисленные константы, которые обрабатываются как 32-разрядные целые числа.Enums are constant integers and are treated as 32-bit integers. В таблице ниже представлены определения типов и рекомендуемое место для хранения данных при использовании следующих значений выравнивания:The following table describes the type definition and recommended storage for data as it pertains to alignment using the following alignment values:

  • байт — 8 битов;Byte - 8 bits

  • слово — 16 битов;Word - 16 bits

  • двойное слово — 32 бита;Doubleword - 32 bits

  • учетверенное слово — 64 бита;Quadword - 64 bits

  • увосьмеренное слово — 128 битов.Octaword - 128 bits

Скалярный типScalar Type Тип данных в CC Data Type Занимаемое место в памяти (в байтах)Storage Size (in bytes) Рекомендуемое выравниваниеRecommended Alignment
INT8 char 11 ByteByte
UINT8 unsigned char 11 ByteByte
INT16 short 22 СловоWord
UINT16 unsigned short 22 СловоWord
INT32 int, longint, long 44 Двойное словоDoubleword
UINT32 unsigned int, unsigned longunsigned int, unsigned long 44 Двойное словоDoubleword
INT64 __int64 88 Учетверенное словоQuadword
UINT64 unsigned __int64 88 Учетверенное словоQuadword
FP32 (одиночная точность)FP32 (single precision) float 44 Двойное словоDoubleword
FP64 (двойная точность)FP64 (double precision) double 88 Учетверенное словоQuadword
POINTER * 88 Учетверенное словоQuadword
__m64 struct __m64 88 Учетверенное словоQuadword
__m128 struct __m128 1616 Увосьмеренное словоOctaword

Статические выражения и объединенияAggregates and unions

Другие типы, такие как массивы, структуры и объединения, предъявляют более строгие требования к выравниванию, обеспечивающие согласованное извлечение статических выражений и объединений.Other types, such as arrays, structs, and unions, have stricter alignment requirements that ensure consistent aggregate and union storage and data retrieval. Ниже приведены определения для массивов, структур и объединений.Here are the definitions for array, structure, and union:

  • МассивArray

    Содержит упорядоченную группу смежных объектов данных.Contains an ordered group of adjacent data objects. Каждый объект называется элементом.Each object is called an element. Все элементы массива имеют одинаковый размер и тип данных.All elements within an array have the same size and data type.

  • structureStructure

    Содержит упорядоченную группу объектов данных.Contains an ordered group of data objects. В отличие от элементов массива, объекты данных в структуре могут иметь разные типы данных и размеры.Unlike the elements of an array, the data objects within a structure can have different data types and sizes. Каждый объект данных в структуре называется элементом.Each data object in a structure is called a member.

  • ОбъединениеUnion

    Объект, содержащий любой из наборов именованных элементов.An object that holds any one of a set of named members. Элементы именованного набора могут быть любого типа.The members of the named set can be of any type. Объем памяти, выделяемый для объединения, равен объему памяти, необходимому для хранения наибольшего его элемента, к которому прибавляется заполнение, требуемое для выравнивания.The storage allocated for a union is equal to the storage required for the largest member of that union, plus any padding required for alignment.

В приведенной ниже таблице показано настоятельно рекомендуемое выравнивание для скалярных элементов объединений и структур.The following table shows the strongly suggested alignment for the scalar members of unions and structures.

Скалярный типScalar Type Тип данных в CC Data Type Требуемое выравниваниеRequired Alignment
INT8 char ByteByte
UINT8 unsigned char ByteByte
INT16 short WordWord
UINT16 unsigned short WordWord
INT32 int, longint, long Двойное словоDoubleword
UINT32 unsigned int, unsigned longunsigned int, unsigned long Двойное словоDoubleword
INT64 __int64 Учетверенное словоQuadword
UINT64 unsigned __int64 Учетверенное словоQuadword
FP32 (одиночная точность)FP32 (single precision) float Двойное словоDoubleword
FP64 (двойная точность)FP64 (double precision) double Учетверенное словоQuadword
POINTER * Учетверенное словоQuadword
__m64 struct __m64 Учетверенное словоQuadword
__m128 struct __m128 Увосьмеренное словоOctaword

В отношении выравнивания статистического выражения действуют следующие правила:The following aggregate alignment rules apply:

  • Выравнивание массива совпадает с выравниванием одного из его элементов.The alignment of an array is the same as the alignment of one of the elements of the array.

  • Выравнивание начала структуры или объединения соответствует максимальному выравниванию любого отдельного элемента.The alignment of the beginning of a structure or a union is the maximum alignment of any individual member. Каждый элемент структуры или объединения должен быть правильно выровнен в соответствии с приведенной выше таблицей, для чего может потребоваться неявное внутреннее заполнение в зависимости от предыдущего элемента.Each member within the structure or union must be placed at its proper alignment as defined in the previous table, which may require implicit internal padding, depending on the previous member.

  • Размер структуры должен быть кратен ее выравниванию, для чего может потребоваться заполнение после последнего элемента.Structure size must be an integral multiple of its alignment, which may require padding after the last member. Так как структуры и объединения могут объединяться в массивы, каждый элемент массива, представляющий собой структуру или объединение, должен начинаться и заканчиваться в ранее определенной позиции выравнивания.Since structures and unions can be grouped in arrays, each array element of a structure or union must begin and end at the proper alignment previously determined.

  • Данные можно выравнивать с превышением требований к выравниванию при условии, что предыдущие правила соблюдаются.It is possible to align data in such a way as to be greater than the alignment requirements as long as the previous rules are maintained.

  • Отдельный компилятор может настроить упаковку структуры с целью ограничения ее размера.An individual compiler may adjust the packing of a structure for size reasons. Например, /Zp (выравнивание члена структуры) позволяет настраивать упаковку структур.For example /Zp (Struct Member Alignment) allows for adjusting the packing of structures.

Примеры выравнивания структурыExamples of Structure Alignment

В каждом из приведенных ниже четырех примеров объявляется выровненная структура или выровненное объединение, а на соответствующих рисунках показано размещение структуры или объединения в памяти.The following four examples each declare an aligned structure or union, and the corresponding figures illustrate the layout of that structure or union in memory. Каждый столбец на рисунке представляет байт памяти, а число в столбце соответствует смещению этого байта.Each column in a figure represents a byte of memory, and the number in the column indicates the displacement of that byte. Имя во второй строке на каждом рисунке соответствует имени переменной в объявлении.The name in the second row of each figure corresponds to the name of a variable in the declaration. Затененные столбцы обозначают заполнение, необходимое для обеспечения указанного выравнивания.The shaded columns indicate padding that is required to achieve the specified alignment.

Пример 1Example 1

// Total size = 2 bytes, alignment = 2 bytes (word).

_declspec(align(2)) struct {
    short a;      // +0; size = 2 bytes
}

Пример преобразования AMD 1: размещение структурыAMD conversion example 1 structure layout

Пример 2Example 2

// Total size = 24 bytes, alignment = 8 bytes (quadword).

_declspec(align(8)) struct {
    int a;       // +0; size = 4 bytes
    double b;    // +8; size = 8 bytes
    short c;     // +16; size = 2 bytes
}

Пример преобразования AMD 2: размещение структурыAMD conversion example 2 structure layout

Пример 3Example 3

// Total size = 12 bytes, alignment = 4 bytes (doubleword).

_declspec(align(4)) struct {
    char a;       // +0; size = 1 byte
    short b;      // +2; size = 2 bytes
    char c;       // +4; size = 1 byte
    int d;        // +8; size = 4 bytes
}

Пример преобразования AMD 3: размещение структурыAMD conversion example 3 structure layout

Пример 4Example 4

// Total size = 8 bytes, alignment = 8 bytes (quadword).

_declspec(align(8)) union {
    char *p;      // +0; size = 8 bytes
    short s;      // +0; size = 2 bytes
    long l;       // +0; size = 4 bytes
}

Пример преобразования AMD 4: размещение объединенияAMD conversion example 4 union layout

РазрядыBitfields

Битовые поля структуры ограничены 64 битами и могут иметь тип signed int, unsigned int, int64 или unsigned int64.Structure bit fields are limited to 64 bits and can be of type signed int, unsigned int, int64, or unsigned int64. При пересечении границы типа битовыми полями будут пропускаться биты для выравнивания поля по следующей границе.Bit fields that cross the type boundary will skip bits to align the bitfield to the next type alignment. Например, битовые поля типа integer не могут пересекать границу в 32 бита.For example, integer bitfields may not cross a 32-bit boundry.

Конфликты с компилятором x86Conflicts with the x86 compiler

Типы данных размером более 4 байт не выравниваются в стеке автоматически при использовании компилятора x86 для компиляции приложения.Data types that are larger than 4 bytes are not automatically aligned on the stack when you use the x86 compiler to compile an application. Так как архитектура компилятора x86 представляет собой 4-байтовый выровненный стек, то все типы больше 4 байт, например 64-разрядные целые числа, не могут автоматически выравниваться по 8-байтовому адресу.Because the architecture for the x86 compiler is a 4 byte aligned stack, anything larger than 4 bytes, for example, a 64-bit integer, cannot be automatically aligned to an 8-byte address.

Работа с невыровненными данными имеет два последствия.Working with unaligned data has two implications.

  • Доступ к невыровненным данным может осуществляться медленнее, чем к выровненным.It may take longer to access unaligned locations than it takes to access aligned locations.

  • Невыровненные расположения нельзя использовать в блокируемых операциях.Unaligned locations cannot be used in interlocked operations.

Если требуется более строгое выравнивание, используйте __declspec(align(N)) в объявлениях переменных.If you require more strict alignment, use __declspec(align(N)) on your variable declarations. В результате компилятор будет динамически выравнивать стек в соответствии с вашими спецификациями.This causes the compiler to dynamically align the stack to meet your specifications. Однако динамическая настройка стека во время выполнения может привести к более медленному выполнению приложения.However, dynamically adjusting the stack at run time may cause slower execution of your application.

Использование регистровRegister usage

Архитектура x64 предоставляет 16 регистров общего назначения (которые далее называются целочисленными регистрами), а также 16 регистров XMM/YMM для значений с плавающей запятой.The x64 architecture provides for 16 general-purpose registers (hereafter referred to as integer registers) as well as 16 XMM/YMM registers available for floating-point use. Переменные регистры — это оперативные регистры, которые вызывающий объект считает очищаемыми во время вызова.Volatile registers are scratch registers presumed by the caller to be destroyed across a call. Неизменяемые регистры должны сохранять свое значение во время вызова функции и при использовании должны сохраняться вызываемым объектом.Nonvolatile registers are required to retain their values across a function call and must be saved by the callee if used.

Изменчивость и сохранение регистровRegister volatility and preservation

Следующая таблица описывает использование каждого из регистров в вызовах функций.The following table describes how each register is used across function calls:

РегистровоеRegister StatusStatus ИспользоватьUse
RAXRAX ПеременныйVolatile Регистр возвращаемого значенияReturn value register
RCXRCX ПеременныйVolatile Первый целочисленный аргументFirst integer argument
RDXRDX ПеременныйVolatile Второй целочисленный аргументSecond integer argument
R8R8 ПеременныйVolatile Третий целочисленный аргументThird integer argument
R9R9 ПеременныйVolatile Четвертый целочисленный аргументFourth integer argument
R10:R11R10:R11 ПеременныйVolatile Должен сохраняться вызывающим объектом; используется в инструкциях syscall/sysret.Must be preserved as needed by caller; used in syscall/sysret instructions
R12:R15R12:R15 НеизменяемыйNonvolatile Должен сохраняться вызываемым объектом.Must be preserved by callee
RDIRDI НеизменяемыйNonvolatile Должен сохраняться вызываемым объектом.Must be preserved by callee
RSIRSI НеизменяемыйNonvolatile Должен сохраняться вызываемым объектом.Must be preserved by callee
RBXRBX НеизменяемыйNonvolatile Должен сохраняться вызываемым объектом.Must be preserved by callee
RBPRBP НеизменяемыйNonvolatile Может использоваться в качестве указателя фрейма; должен сохраняться вызываемым объектом.May be used as a frame pointer; must be preserved by callee
RSPRSP НеизменяемыйNonvolatile Указатель стекаStack pointer
XMM0, YMM0XMM0, YMM0 ПеременныйVolatile Первый аргумент FP; первый аргумент векторного типа при использовании __vectorcallFirst FP argument; first vector-type argument when __vectorcall is used
XMM1, YMM1XMM1, YMM1 ПеременныйVolatile Второй аргумент FP; второй аргумент векторного типа при использовании __vectorcallSecond FP argument; second vector-type argument when __vectorcall is used
XMM2, YMM2XMM2, YMM2 ПеременныйVolatile Третий аргумент FP; третий аргумент векторного типа при использовании __vectorcallThird FP argument; third vector-type argument when __vectorcall is used
XMM3, YMM3XMM3, YMM3 ПеременныйVolatile Четвертый аргумент FP; четвертый аргумент векторного типа при использовании __vectorcallFourth FP argument; fourth vector-type argument when __vectorcall is used
XMM4, YMM4XMM4, YMM4 ПеременныйVolatile Должен сохраняться вызывающим объектом; пятый аргумент векторного типа при использовании __vectorcallMust be preserved as needed by caller; fifth vector-type argument when __vectorcall is used
XMM5, YMM5XMM5, YMM5 ПеременныйVolatile Должен сохраняться вызывающим объектом; шестой аргумент векторного типа при использовании __vectorcallMust be preserved as needed by caller; sixth vector-type argument when __vectorcall is used
XMM6:XMM15, YMM6:YMM15XMM6:XMM15, YMM6:YMM15 Неизменяемый (XMM), переменный (верхняя половина YMM)Nonvolatile (XMM), Volatile (upper half of YMM) Должен сохраняться вызываемым объектом.Must be preserved by callee. Регистры YMM должны сохраняться вызывающим объектом.YMM registers must be preserved as needed by caller.

При выходе из функций и входе функций в вызовы библиотеки времени выполнения C и системные вызовы Windows флаг направления в регистре флагов ЦП должен сбрасываться.On function exit and on function entry to C Runtime Library calls and Windows system calls, the direction flag in the CPU flags register is expected to be cleared.

Использование стекаStack usage

Подробные сведения о выделении стека, выравнивании, типах функций и кадрах стека в архитектуре x64 см. в статье Использование стека для 64-разрядных систем.For details on stack allocation, alignment, function types and stack frames on x64, see x64 stack usage.

Пролог и эпилогProlog and epilog

Каждая функция, которая выделяет пространство стека, вызывает другие функции, сохраняет энергонезависимые регистры или использует обработку исключений, должна содержать пролог с ограничениями адресов, описанными в данных очистки, связанных с соответствующей записью таблицы функций, и эпилоги при каждом выходе из функции.Every function that allocates stack space, calls other functions, saves nonvolatile registers, or uses exception handling must have a prolog whose address limits are described in the unwind data associated with the respective function table entry, and epilogs at each exit to a function. Подробные сведения о необходимом коде пролога и эпилога в архитектуре x64 см. в статье Пролог и эпилог для 64-разрядных систем.For details on the required prolog and epilog code on x64, see x64 prolog and epilog.

Обработка исключений в 64-разрядных системахx64 exception handling

Сведения о соглашениях и структурах данных для реализации структурированной обработки исключений и обработки исключений C++ в архитектуре x64 см. в статье Обработка исключений в 64-разрядных системах.For information on the conventions and data structures used to implement structured exception handling and C++ exception handling behavior on the x64, see x64 exception handling.

Внутренний и подставляемый ассемблерный кодIntrinsics and inline assembly

Одним из ограничений для компилятора x64 является отсутствие поддержки встроенного ассемблера.One of the constraints for the x64 compiler is to have no inline assembler support. Это означает, что функции, которые нельзя написать на языке C или C++, должны создаваться как подпрограммы или как встроенные функции, поддерживаемые компилятором.This means that functions that cannot be written in C or C++ will either have to be written as subroutines or as intrinsic functions supported by the compiler. Для некоторых функций производительность важна, а для других нет.Certain functions are performance sensitive while others are not. Функции, для которых производительность важна, должны реализовываться как встроенные.Performance-sensitive functions should be implemented as intrinsic functions.

Встроенные функции, поддерживаемые компилятором, описываются в разделе Встроенные инструкции компилятора.The intrinsics supported by the compiler are described in Compiler Intrinsics.

Формат образаImage format

Формат исполняемого образа x64 — PE32+.The x64 executable image format is PE32+. Размер исполняемых образов (как DLL, так и EXE) ограничен 2 гигабайтами, поэтому для адресации статических данных образов можно использовать относительную адресацию с 32-битным смещением.Executable images (both DLLs and EXEs) are restricted to a maximum size of 2 gigabytes, so relative addressing with a 32-bit displacement can be used to address static image data. Эти данные включают в себя таблицу адресов импорта, строковые константы, статические глобальные данные и т. д.This data includes the import address table, string constants, static global data, and so on.

См. такжеSee also

Соглашения о вызовахCalling Conventions