9

I am reading one of Agner Fog's manuals and as an advantage for 64 bit Operating Systems (over 32 bit) he says:

Function parameters are transferred in registers rather than on the stack. This makes function calls more efficient.

Is he saying the stack is not used for passing function parameters (64bit OS) at all???

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
user997112
  • 29,025
  • 43
  • 182
  • 361

1 Answers1

19

Yes, that's what he's saying, but it's not quite accurate. The stack may be used, but only if your function has a lot of parameters (or you write code that forces a spill).

If you check out the wikipedia list of 64-bit intel calling conventions, you'll see that registers are used to pass the first several parameters. There are two major 64-bit Intel calling conventions. For the Microsoft ABI:

The Microsoft x64 calling convention uses registers RCX, RDX, R8, R9 for the first four integer or pointer arguments (in that order left to right), and XMM0, XMM1, XMM2, XMM3 are used for floating point arguments. Additional arguments are pushed onto the stack (right to left). Integer return values (similar to x86) are returned in RAX if 64 bits or less. Floating point return values are returned in XMM0. Parameters less than 64 bits long are not zero extended; the high bits contain garbage.

And the System V ABI:

The first six integer or pointer arguments are passed in registers RDI, RSI, RDX, RCX, R8, and R9, while XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6 and XMM7 are used for floating point arguments ... As in the Microsoft x64 calling convention, additional arguments are passed on the stack and the return value is stored in RAX.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
  • I guess this is related to another statement he makes saying 64 bit Linux can pass more parameters into registers than Windows 64 bit? "In 64 bit Linux the first six integer parameters and first eight floating point parameters are transferred into registers. In 64 bit Windows the first 4 parameters are transferred....." – user997112 Jul 02 '13 at 23:04
  • Yes, that's correct. Linux uses the SYSV ABI, which uses more registers for parameter passing. – Carl Norum Jul 02 '13 at 23:04
  • Is that SYSV ABI something which has always been "hidden" within Intel CPUs and that Linux chose to take advantage of, but not Windows? – user997112 Jul 02 '13 at 23:06
  • 1
    There's nothing about the CPU that affects this behaviour, really. Calling conventions are just that - conventions. It's arbitrary, and they just happen to be different. You could pass parameters in registers for 32-bit code, too (ARM does that for example), there's just not a common Intel ABI that does so. – Carl Norum Jul 02 '13 at 23:07
  • I'm just looking at a document for System V ABI and it was written back in 1997- so how can that have known how many registers would be available for use, say with the SIMD XMM registers etc? In other words what does the ABI do/tell me? – user997112 Jul 02 '13 at 23:11
  • 1
    It's just a decision. I guess the guys at MS decided they wanted more caller-saved registers. It's not better or worse to have different conventions, they're just *different*. "ABI" stands for "application binary interface". Your compiler will generate different code depending on which ABI you target, but that's not really what it's about. The goal is to define an interface that already-compiled code can use to interact with other already-compiled code - so your program can call functions in a library, for example. – Carl Norum Jul 02 '13 at 23:11
  • 1
    [More about ABIs from wikipedia.](http://en.wikipedia.org/wiki/Application_binary_interface) – Carl Norum Jul 02 '13 at 23:13
  • Ooh, what about variable arguments? – Kerrek SB Jul 02 '13 at 23:23
  • What about them? They work like normal function calls on SYSV, as far as I know. I think there might be a count of how many floating point arguments there are added in there too. The appropriate documentation describes it, I'm sure. – Carl Norum Jul 02 '13 at 23:24
  • @user997112 - if you check the citations on the x86 calling conventions wikipedia page, you'll see that the AMD supplement was last published in 2012. – Carl Norum Jul 02 '13 at 23:27
  • @KerrekSB - confirmed. "`%rax`: temporary register; with variable arguments passes information about the number of SSE registers used; 1st return register" – Carl Norum Jul 02 '13 at 23:30
  • Typically for variable-arguments functions you do one (or both) of two things: pass arguments differently from the caller (making them easily accessible in memory), or, have the callee stuff the (passed as for fixed-argument functions) arguments into memory. The x86 SysV ABI does the latter. There are lots of variations on this general theme, which gets tricky when mixing integer and FP arguments. If you make the caller do it, it's simpler, but fails when the programmer forgets to declare `printf`.... – torek Jul 02 '13 at 23:39
  • 1
    Related: [Why does Windows64 use a different calling convention from all other OSes on x86-64?](https://stackoverflow.com/q/4429398) – Peter Cordes Oct 24 '20 at 13:53