Передача параметров
Обновлен: Ноябрь 2007
Первые четыре аргумента целых чисел передаются в регистры. Значения целых чисел передаются (слева направо) в RCX, RDX, R8 и R9. Остальные аргументы (после первых четырех) передаются в стек. Все аргументы в регистрах выравниваются по правому краю. Это делается для того, чтобы вызываемый мог игнорировать старшие разряды регистра при необходимости и получить доступ только к необходимой части регистра.
Аргументы значений с плавающей запятой и двойной точностью передаются в XMM0 – XMM3 (до 4) с помощью гнезда целых чисел (RCX, RDX, R8 и R9), которое обычно и используется, в то время как гнездо кардинальных чисел отклоняется (см. пример) и наоборот.
__m128 типы, массивы и строки никогда не передаются в виде непосредственных значений, а передаются как указатель на область памяти, выделенную вызывающим. 8, 16, 32 или 64-разрядные структуры/объединения и указатель _m64 передаются, как если они были бы целыми числами одинакового размера. Структуры/объединения других размеров должны передаваться как указатель на область памяти, выделенную оператором. Для этих агрегатных типов, передаваемых в качестве указателя (включая __m128), память должна быть выровнена по 16 разряду.
Встроенные функции, которые не выделяют пространства в стеке и не вызывают других функций, могут использовать иные изменяемые регистры для передачи дополнительных аргументов в регистры, так как существует тесная связь между компилятором и реализацией встроенной функции. Это дополнительная возможность увеличения производительности.
Вызываемый несет ответственность за сбрасывание при необходимости параметров регистра в теневое пространство.
В следующей таблице подведены итоги передачи параметров:
Тип параметра |
Передача |
---|---|
С плавающей запятой |
Первые 4 параметра — от XMM0 к XMM3. Остальные передаются в стек. |
Целое число |
Первые 4 параметра — RCX, RDX, R8, R9. Остальные передаются в стек. |
Агрегатные параметры (8, 16, 32 или 64-разрядные) и __m64 |
Первые 4 параметра — RCX, RDX, R8, R9. Остальные передаются в стек. |
Агрегатные параметры (другие) |
Указатель. Первые 4 параметра, переданные в качестве указателей в RCX, RDX, R8 и R9 |
__m128 |
Указатель. Первые 4 параметра, переданные в качестве указателей в RCX, RDX, R8 и R9 |
Пример передачи аргумента 1 — все целые числа
func1(int a, int b, int c, int d, int e);
// a in RCX, b in RDX, c in R8, d in R9, e pushed on stack
Пример передачи аргумента 2 — все с плавающей запятой
func2(float a, double b, float c, double d, float e);
// a in XMM0, b in XMM1, c in XMM2, d in XMM3, e pushed on stack
Пример передачи аргумента 3 — вперемешку целые и с плавающей запятой
func3(int a, double b, int c, float d);
// a in RCX, b in XMM1, c in R8, d in XMM3
Пример передачи аргумента 4 — __m64, __m128 и агрегатные параметры
func4(__m64 a, _m128 b, struct c, float d);
// a in RCX, ptr to b in RDX, ptr to c in R8, d in XMM3