-1

If we have the following function:

int func(int n, float f, char* s, double* d);

The call to the function in Assembly will be like that:

movl <n>, %ecx
movl <s>, %edx
pushl <d>
pushl <f>
call func

Is this correct? Why it's in this order? It's because of the size of each type?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Pedro Gómez
  • 214
  • 1
  • 8
  • 2
    First, choose an architecture, then try it with a compiler to see. – Erik Eidt May 01 '21 at 14:55
  • Is that supposed to be Windows 32-bit fastcall? – Peter Cordes May 01 '21 at 15:03
  • @PeterCordes Yes! You know to explain why it's in this order? – Pedro Gómez May 01 '21 at 15:04
  • 2
    The first two eligible args go into ECX and EDX in that order, then on the stack with the left-most stack-arg at the lowest address (pushed last). Seems reasonable to me, assuming that that matches what a compiler does; check MSVC on https://godbolt.org/ – Peter Cordes May 01 '21 at 15:06
  • @PeterCordes What do you mean eligible args? – Pedro Gómez May 01 '21 at 15:08
  • Also, all four args are the same size, 32-bit, in 32-bit x86 ABIs. (int, float, and pointers) – Peter Cordes May 01 '21 at 15:08
  • 2
    Eligible: I mean args that the calling convention will allow to be passed in registers: integer and pointer args, but not `float` or `double`. I assume MS documents `__fastcall` somewhere; go read their docs for details on the rules. – Peter Cordes May 01 '21 at 15:09
  • @PeterCordes Thanks! In general which args is allowed to be passed in registers? Only int and pointers? – Pedro Gómez May 01 '21 at 15:10
  • 1
    Related: [Why not store function parameters in XMM vector registers?](https://stackoverflow.com/a/33707435) for the opposite question of why not pass more integers in FP registers. The rules for exactly which args can be passed in integer registers depends on the calling convention. Certainly pointers and integral types, and certainly not FP, but the design choice for structs (by value) isn't obvious; you have to check the docs or what compilers actually do. – Peter Cordes May 01 '21 at 15:11

1 Answers1

0

For known arguments, there is not a strong compelling reason to push right-to-left or the other way around, so it's just a convention to follow.

For variable arguments it's a benefit to push them in the reversed order because the callee doesn't know how many arguments were passed. but the first argument is in a known position, i.e. right after the return address.

So if you consider the example of printf:

 printf(FormatString, a1, a2, a3, a4);

So FormatString is now in a known position and can easily find the other parameters going through the stack.

If it were the other way around, then the callee would need to get some additional information in order to find the first argument, Either a pointer, or a counter or something, that tells it, where the formatstring is found.

Devolus
  • 21,661
  • 13
  • 66
  • 113