Search code examples
assemblyx86-64masmcpu-registerscalling-convention

Does RCX need be be preserved for X64 Fastcall Leaf Functions?


I have a X64 ASM routine assembled with MASM64/ML64. Its a stand alone leaf function, and not inline assembly. It is used in a C/C++ program within a Visual Studio solution.

I found two references on preserving registers on MSDN:

The first is for inline assembly, but it specifically states to preserve ECX when using __fastcall. It also appears to lack a treatment of X64 because it refers to 32-bit registers.

The second tells us "RAX, RCX, RDX, R8, R9, R10, R11 are considered volatile and must be considered destroyed on function calls". Unfortunately, it does not clearly state whether they need to be preserved. (If you look closely, its using misdirection rather than stating the action to take).

I think the second article is controlling in this case, but I want to be clear to avoid confusion... Does CX/ECX/RCX need be be preserved for X64 Fastcall Leaf Functions?


Solution

  • The "Using and Preserving Registers in Inline Assembly" article discusses only x86 and does not apply to x86-64.

    The "Caller/Callee Saved Registers" article is about the x86-64 calling convention, and clearly states that the RCX register is volatile so does not need to be saved by the callee.

    A comment by @rkhb mentions that the "Overview of x64 Calling Conventions" article is the source of the confusion, presumably because it says:

    x64 just uses the __fastcall calling convention and a RISC-based exception-handling model

    However, if you follow the __fastcall link in that quote, you'll see that it says, "This calling convention [__fastcall] only applies to the x86 architecture". I think that the Overview article really means to say something like, "x64 uses a calling convention similar to __fastcall where registers are used to pass arguments".