Согласно https://docs.microsoft.com/ru-ru/cpp/build/x64-software-conventions?view=vs-2017 — xmm6:xmm15 энергонезависимы. Но моя программа не падает, если я не сохраняю xmm6, xmm7. Я не вызываю ОС из сборки. Нужно ли сохранять регистры в этом случае? Я работаю под Windows 7.
Сохранение реестра msvc 2017 x64
Ответы (1)
Взлом ABI не гарантирует ошибки, точно так же, как UB в C может сработать. например возможно, вызывающий абонент сохраняет/восстанавливает (при входе/выходе) регистр XMM, который вы уничтожаете, но не заботится об их значениях при вызове вашей функции. например возможно, он хотел сохранить значение FP в регистре при вызове printf
, а не при вызове вашей функции.
Или, возможно, их никто не использует, и main
и коду запуска CRT все равно.
Способ, которым ABI гарантирует работу, заключается в том, что если вы следуете им, вы гарантируете отсутствие проблем, а не наоборот.
IDK, если есть функция-оболочка "проверки" соглашения о вызовах, которая проверяет, правильно ли сохранены все регистры, сохраненные при вызове, и что вы не наступили на какое-либо пространство стека за пределами теневого пространства и (если есть) ваши аргументы стека. Наверное, кто-то писал что-то подобное. например Написание переходника для проверки соответствия SysV ABI
Было бы здорово не сохранять эти регистры, потому что это влияет на производительность (не сильно, но все же).
Если вы компилируете свой C с помощью GCC или clang, вы можете объявить прототип вашей ассемблерной функции как использующий x86-64 System V ABI, где все xmm0..15 затираются вызовами (и передача аргументов использует разные регистры), используя атрибут функции GCC
__attribute__((sysv_abi))
extern "C" int myfunc(void);
Затем вызывающая сторона должна будет сохранить/восстановить все из xmm6..15, поскольку предполагается, что вызывающая сторона уничтожила их все.
Поэтому сделайте это для функции, достаточно высоко стоящей в дереве вызовов, чтобы эти накладные расходы амортизировались за многие вызовы функций.
(Или лучше используйте встроенные функции, чтобы использование регистров XMM можно было встроить и оптимизировать накладные расходы на вызов/возврат, а также накладные расходы на сохранение/восстановление регистра XMM. Если накладные расходы на сохранение/восстановление или вызов имеют значение, решение более встроенное, поэтому функции не такие маленькие.)
См. Обход соглашения о вызовах Windows с сохранением регистров xmm? для этого . Имейте в виду, что ICC глючит и не может сохранить/восстановить XMM6..15 вокруг вызова функции System V ABI, а GCC не поддерживает должным образом AVX в Windows (проблемы выравнивания стека).