问题
My Windows program compiled using Visual Studio 2017 does the following:
- calls a routine that has a default argument with value 35.05.
- initializes the Java Virtual Machine through the C interface
- calls the routine again that has the default argument with value 35.05.
In the first call, the default argument gets the correct 35.05. In the second call that value is garbage.
I looked at the generated assembly and during the first call with the default argument 35.05 is copied to xmm8
from a memory location and it's copied to the stack (it's the 5th parameter) and the call is made:
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]
Then the call is made to initialize the JVM.
Then for the next call, xmm8
is used again to copy the value to the stack:
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]
But now, xmm8
has been overwritten.
If I take out the call to initialize the JVM, then the value is preserved.
The question is, who's in the wrong here? JVM is not preserving the value or Microsoft compiler was in the wrong to assume xmm8
value will be preserved.
回答1:
The Windows x64 calling convention summarized from Microsoft docs.
RCX
, RDX
, R8
, and R9
are used as input integer parameters. XMM0L
, XMM1L
, XMM2L
, and XMM3L
are input floating-point parameters. RAX
, R10
, R11
, XMM4
, and XMM5
are volatile. All others including XMM8
are non-volatile.
Note that the "Caller/Callee Saved Registers" sub-page is a bit misleading right now because it doesn't include the SSE registers.
UPDATE: Any additional registers for newer instruction sets are volatile by default. This includes the upper parts of YMM0-15
and ZMM0-15
as well as ?MM16-31
if present.
来源:https://stackoverflow.com/questions/53733624/is-xmm8-register-value-preserved-across-calls