msvc 2017 x64 寄存器保存
msvc 2017 x64 register preservation
根据 https://docs.microsoft.com/ru-ru/cpp/build/x64-software-conventions?view=vs-2017 - xmm6:xmm15 是非易失性的。但是如果我不保留 xmm6、xmm7,我的程序就不会崩溃。我不从程序集调用 OS。在这种情况下我需要保留寄存器吗?我是 运行 下的 Windows 7.
破坏 ABI 并不能保证一个错误,就像 C 中的 UB 可能碰巧工作一样。例如可能是调用者 saves/restores(在 entry/exit 上)您销毁的 XMM reg,但在对 您的 函数的调用中不关心它们的值。例如也许它想在 printf
调用中将 FP 值保存在寄存器中,而不是在对函数的调用中。
或者也许没有什么用到它们,main
和 CRT 启动代码不关心。
ABI 保证工作的方式是,如果你遵循它们,你保证没有问题,而不是相反。
IDK 如果有一个调用约定 "checker" 包装函数验证所有调用保留的 regs 是否被正确保存,并且你没有踩到阴影之外的任何堆栈 space space 和(如果有的话)你的堆栈参数。可能有人写过类似的东西。例如Writing a thunk to verify SysV ABI compliance
It would be great to avoid saving these registers because it affects performance (not much but still).
如果您使用 GCC 或 clang 编译 C,您可以将 asm 函数的原型声明为使用 x86-64 System V ABI,其中所有 xmm0..15 都被调用破坏(并且 arg-passing 使用不同的寄存器),使用 GCC function attribute
__attribute__((sysv_abi))
extern "C" int myfunc(void);
然后调用者将必须 save/restore all xmm6..15 因为它必须假定被调用者将它们全部销毁。
因此,对调用树上足够高的函数执行此操作,以便将此开销分摊到许多函数调用中。
(或者更好,使用内在函数,这样您对 XMM reg 的使用可以内联 并优化 call/ret 开销以及 save/restore XMM reg开销。如果 save/restore 或调用开销很重要,解决方案是更多的内联,所以函数不会那么小。)
参见 。请注意,ICC 存在问题并且无法 save/restore XMM6..15 围绕对 System V ABI 函数的调用,并且 GCC 在 Windows 上不正确支持 AVX(堆栈对齐问题)。
根据 https://docs.microsoft.com/ru-ru/cpp/build/x64-software-conventions?view=vs-2017 - xmm6:xmm15 是非易失性的。但是如果我不保留 xmm6、xmm7,我的程序就不会崩溃。我不从程序集调用 OS。在这种情况下我需要保留寄存器吗?我是 运行 下的 Windows 7.
破坏 ABI 并不能保证一个错误,就像 C 中的 UB 可能碰巧工作一样。例如可能是调用者 saves/restores(在 entry/exit 上)您销毁的 XMM reg,但在对 您的 函数的调用中不关心它们的值。例如也许它想在 printf
调用中将 FP 值保存在寄存器中,而不是在对函数的调用中。
或者也许没有什么用到它们,main
和 CRT 启动代码不关心。
ABI 保证工作的方式是,如果你遵循它们,你保证没有问题,而不是相反。
IDK 如果有一个调用约定 "checker" 包装函数验证所有调用保留的 regs 是否被正确保存,并且你没有踩到阴影之外的任何堆栈 space space 和(如果有的话)你的堆栈参数。可能有人写过类似的东西。例如Writing a thunk to verify SysV ABI compliance
It would be great to avoid saving these registers because it affects performance (not much but still).
如果您使用 GCC 或 clang 编译 C,您可以将 asm 函数的原型声明为使用 x86-64 System V ABI,其中所有 xmm0..15 都被调用破坏(并且 arg-passing 使用不同的寄存器),使用 GCC function attribute
__attribute__((sysv_abi))
extern "C" int myfunc(void);
然后调用者将必须 save/restore all xmm6..15 因为它必须假定被调用者将它们全部销毁。
因此,对调用树上足够高的函数执行此操作,以便将此开销分摊到许多函数调用中。
(或者更好,使用内在函数,这样您对 XMM reg 的使用可以内联 并优化 call/ret 开销以及 save/restore XMM reg开销。如果 save/restore 或调用开销很重要,解决方案是更多的内联,所以函数不会那么小。)
参见