That is platform specific and part of the "ABI". In fact, some compilers even allow you to choose between different conventions.
Microsoft's Visual Studio, for example, offers the __fastcall calling convention, which uses registers. Other platforms or calling conventions use the stack exclusively.
Variadic arguments work in a very similar way - they are passed via registers or stack. In case of registers, they are usually in ascending order, based on type. If you have something like (int a, int b, float c, int d), a PowerPC ABI might put a
in r3, b
in r4, d
in r5, and c
in fp1 (I forgot where float registers start, but you get the idea).
Return values, again, work the same way.
Unfortunately, I don't have many examples, most of my assembly is in PowerPC, and all you see in the assembly is the code going straight for r3, r4, r5, and placing the return value in r3 as well.