Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

x64 calling convention (stack) and varargs

I've read Microsoft's documentation, but the scheme is so awkward, I thought I'd double-check to make sure I'm understanding it correctly...

My understanding is the generic method by which parameters are passed is this:

--- bottom of stack ---
(return address)
[shadow space for arg 1]
[shadow space for arg 2]
[shadow space for arg 3]
[shadow space for arg 4]
arg N
arg N - 1
arg N - 2
...
arg 6
arg 5
---- top of stack -----

It seems so awkward when implementing va_arg and such... is this actually correct?

like image 696
user541686 Avatar asked Aug 23 '12 02:08

user541686


People also ask

How are parameters passed in x64?

Parameter passingBy default, the x64 calling convention passes the first four arguments to a function in registers. The registers used for these arguments depend on the position and type of the argument. Remaining arguments get pushed on the stack in right-to-left order.

What is the difference between Stdcall and cdecl?

In CDECL arguments are pushed onto the stack in revers order, the caller clears the stack and result is returned via processor registry (later I will call it "register A"). In STDCALL there is one difference, the caller doeasn't clear the stack, the calle do. You are asking which one is faster.

What are different calling conventions?

There are three major calling conventions that are used with the C language on 32-bit x86 processors: STDCALL, CDECL, and FASTCALL. In addition, there is another calling convention typically used with C++: THISCALL. There are other calling conventions as well, including PASCAL and FORTRAN conventions, among others.

What calling convention does GCC use?

In Linux, GCC sets the de facto standard for calling conventions. Since GCC version 4.5, the stack must be aligned to a 16-byte boundary when calling a function (previous versions only required a 4-byte alignment). A version of cdecl is described in System V ABI for i386 systems.


1 Answers

The correct diagram is

--- Bottom of stack ---    RSP + size     (higher addresses)
arg N
arg N - 1
arg N - 2
...
arg 6
arg 5
[shadow space for arg 4]
[shadow space for arg 3]
[shadow space for arg 2]
[shadow space for arg 1]
(return address)
---- Top of stack -----    RSP            (lower addresses)
[grows downward]

The return address is at the top of the stack (most recently pushed), followed by shadow space for the first four parameters, followed by parameters 5 and onward.

The parameters are pushed right to left: The last parameter (N) is pushed first, so it is closest to the bottom of the stack.

like image 174
Raymond Chen Avatar answered Oct 05 '22 23:10

Raymond Chen