Win64 против System V ABI (x86_64): Win64 пропускает регистры?

Предположим, у нас есть функция C (или C++) со следующей сигнатурой:

void foo(int64_t a, double b, int64_t c, double d);

При компиляции в Linux, Mac или любой ОС, использующей System V ABI (x86_64), a и c передаются в регистрах rdi и rsi, а b и d передаются в xmm0 и xmm1. Хорошо, в этом нет ничего плохого. Но потом я делаю то же самое в Windows (x86_64), и похоже, что он пропускает некоторые регистры. a и c передаются в rcx и r8 (rdx пропускаются), а b и d передаются в xmm1 и xmm3 (xmm0 и xmm2 пропускаются). Почему Win64 делает это вместо того, чтобы «сжимать» аргументы, как System V? Я предполагаю, что с System V можно передать, скажем, 4 qword и 4 double без необходимости передавать что-либо в стек, тогда как Win64, как я предполагаю, будет передавать все, что находится после 4-го аргумента в стеке.

Я знаю о различиях в порядке регистров при передаче аргументов в Win64 и SysV, но порядок не должен иметь значения. Мне просто любопытно, почему Win64 пропускает регистры, особенно когда у него всего 4 для передачи аргументов без стека.


person Mona the Monad    schedule 15.08.2017    source источник
comment
Совершенно другой abi, я думаю, что старый win abi назывался fastcall, не знаю насчет 64-битного... Я просто знаю, что он другой...   -  person Grady Player    schedule 15.08.2017
comment
Немного сложно ответить, мы могли бы предположить, но, в конце концов, только дизайнеры на самом деле знают свои причины   -  person harold    schedule 15.08.2017
comment
Обратите внимание, что Win64 ABI передает в регистры не более четырех целых аргументов/указателей, тогда как System V ABI передает в регистры до шести аргументов (см. en.wikipedia.org/wiki/X86_calling_conventions). Все четыре, используемые для этой цели в Win64, входят в число шести, используемых в System V. Я не думаю, что вполне уместно говорить, что Win64 ABI пропускает регистры, но определенно назначает меньшее их количество для регистров. использовать. Однако, почему это происходит, я сомневаюсь, что вы получите здесь объяснение.   -  person John Bollinger    schedule 15.08.2017
comment
Я не это имел в виду под пропуском.   -  person Mona the Monad    schedule 16.08.2017
comment
Связано: stackoverflow.com/questions/4429398/. Интересным моментом является то, что в то время Microsoft и Intel поддерживали IA-64, поэтому поддержка MS AMD64 не требовала особых усилий, что может объяснить, почему они выбрали ABI, похожий на 32-битный __fastcall, и простой в реализации вариативный функции, а не новый дизайн для высокой производительности с обычными (невариативными) функциями. (Работаю над ответом на этот вопрос, опубликую позже).   -  person Peter Cordes    schedule 19.08.2017


Ответы (1)


документация Майкрософт

https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-160

утверждает, что они передают не более 4 параметров в регистры. Если один параметр не помещается в определенный регистр, этот регистр просто пропускается.

Аргументы с плавающей запятой и двойной точности передаются в XMM0–XMM3 (до 4), при этом целочисленный слот (RCX, RDX, R8 и R9), который обычно используется для этого кардинального слота, игнорируется (см. пример ) и наоборот.

Пример 3 на связанной странице является именно вашим примером и объясняет эффект, который вы видели:

func3(int a, double b, int c, float d);    
// a in RCX, b in XMM1, c in R8, d in XMM3  

Таким образом, они используют до 4 регистров для параметров, первый параметр либо в RCX, либо в XMM0, второй параметр либо в RDX, либо в XMM1 и т. д.

Так зачем делать это таким образом? Возможно, идея передачи 8 регистровых параметров функциям не казалась важным вариантом использования.

person Bo Persson    schedule 15.08.2017
comment
Мне просто любопытно, оказывает ли это поведение пропуска регистров незначительное влияние на производительность или что-то в этом роде, поскольку Windows, безусловно, не шутка операционной системы. - person Mona the Monad; 16.08.2017
comment
Это означало бы переменное количество исходного пространства для параметров и значительно усложнило бы реализацию функций с переменным числом аргументов. - person Raymond Chen; 16.08.2017