Reputation: 31
Curious where the return address is stored in the x64 Microsoft Fastcall implementation. Cheers.
Upvotes: 1
Views: 3267
Reputation: 364287
Same as every other x86 / x86-64 calling convention, it's on the stack on function entry, pointed to by rsp
. Calls are still made using call
, which pushes an 8-byte absolute return address and jumps to the target address.
So if you run a ret
instruction while RSP has the value it did on entry, it will pop that return address back into RIP. (ret
is how we write pop rip
on x86-64.) This should be clear if you look at compiler generated code which either just uses ret
, or if it moves RSP inside the function, restores it again before running a ret
.
MS documents stack layout for their x64 calling convention.
https://learn.microsoft.com/en-us/cpp/build/stack-usage?view=vs-2019. Also docs for x64 __fastcall in general. (And yes, MS do call it x64 __fastcall
, even though it and x64 __vectorcall
are the only 2 calling conventions they support for x86-64. x64 __fastcall
is slightly similar to 32-bit __fastcall
, but the x64 version is caller-pops the stack and with more registers for arg-passing. And differences in xmm registers being call-preserved. It does use the same first 2 integer registers, though, hence the name I guess.)
Whatever your problem is, it's probably not this. Although you mentioned ESP in comments. If you run sub esp, 8
in 64-bit code, you'll truncate RSP to 32 bits, leading to a fault next time you try to push/pop or call.
Upvotes: 4