【发布时间】: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 值将被保留。
【问题讨论】:
-
xmm8must 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