【问题标题】:Is xmm8 register value preserved across calls?xmm8 寄存器值是否在调用中保留?
【发布时间】:2019-05-13 00:04:50
【问题描述】:

我使用 Visual Studio 2017 编译的 Windows 程序执行以下操作:

  • 调用默认参数值为 35.05 的例程。
  • 通过 C 接口初始化 Java 虚拟机
  • 再次调用默认参数值为 35.05 的例程。

在第一次调用中,默认参数得到正确的 35.05。在第二次调用中,该值是垃圾。

我查看了生成的程序集,并在第一次调用期间使用默认参数 35.05 从内存位置复制到 xmm8 并将其复制到堆栈(这是第 5 个参数)并进行调用:

0033d   48 8b 01     mov     rax, QWORD PTR [rcx]
00340   41 b8 14 00 00
00       mov     r8d, 20 // a default argument
00346   f3 44 0f 10 05
00 00 00 00  movss   xmm8, DWORD PTR __real@420c3333 // this is 35.05
0034f   f3 44 0f 11 44
24 28        movss   DWORD PTR [rsp+40], xmm8
00356   48 c7 44 24 20
1e 00 00 00  mov     QWORD PTR [rsp+32], 30 // a default argument
0035f   45 8d 48 05  lea     r9d, QWORD PTR [r8+5]
00363   b2 0f        mov     dl, 15 // a default argument
00365   ff 90 08 01 00
00       call    QWORD PTR [rax+264]

然后调用初始化JVM。

然后对于下一次调用,再次使用xmm8 将值复制到堆栈中:

00ce8   48 8b 01     mov     rax, QWORD PTR [rcx]
00ceb   41 b8 14 00 00
00       mov     r8d, 20
00cf1   f3 44 0f 11 44
24 28        movss   DWORD PTR [rsp+40], xmm8
00cf8   48 c7 44 24 20
1e 00 00 00  mov     QWORD PTR [rsp+32], 30
00d01   45 8d 48 05  lea     r9d, QWORD PTR [r8+5]
00d05   b2 0f        mov     dl, 15
00d07   ff 90 08 01 00
00       call    QWORD PTR [rax+264]

但现在,xmm8 已被覆盖。

如果我取出调用来初始化 JVM,那么该值将被保留。

问题是,谁错了? JVM 没有保留该值,或者 Microsoft 编译器错误地假设 xmm8 值将被保留。

【问题讨论】:

  • xmm8 must be preserved by callee 所以如果 JVM 真的破坏了xmm8,那么它就是有问题的。
  • 谢谢。该文件没有出现在我所有的谷歌搜索中:(
  • 这是哪个JVM?甲骨文?如果它接受 Windows x64 使用的寄存器中的 args,但 clobbers 不应该注册它,那听起来就坏了。自定义调用约定是可能的,但如果没有 asm 包装器,则无法与编译的 C / C++ 交互。听起来这可能是无意的调用约定差异,即 JVM 中的错误。
  • @PeterCordes 是的,Oracle 和他们已经接受并修复了 bug。我应该提到我使用的是 Java 1.8。

标签: assembly visual-c++ x86-64 cpu-registers abi


【解决方案1】:

Microsoft docs 总结的 Windows x64 调用约定。

RCXRDXR8R9 用作输入整数参数。 XMM0LXMM1LXMM2LXMM3L 是输入浮点参数。 RAXR10R11XMM4XMM5 是不稳定的。包括XMM8 在内的所有其他人都是非易失性的。

请注意,“调用者/被调用者保存的寄存器”子页面现在有点误导,因为它不包括 SSE 寄存器。

更新:默认情况下,新指令集的任何附加寄存器都是易失性的。这包括YMM0-15ZMM0-15 的上部以及?MM16-31(如果存在)。

【讨论】:

  • 值得一提的是,ymm6..15 和 zmm6..31 的高速通道被呼叫破坏了。只有严格的 xmm6..15(低 128 位)被保留调用。我认为,使用 AVX512VL,即使 xmm16..31 也可以被破坏。
  • 我不确定那些额外的寄存器怎么样,但它们可能是易失的。我看看能不能找到人……
  • 任何在创建 ABI 时不存在的东西都是易变的,因为否则就是 BackCompat 问题。
猜你喜欢
  • 1970-01-01
  • 2018-02-27
  • 1970-01-01
  • 1970-01-01
  • 2015-03-27
  • 2021-11-23
  • 2021-01-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多