Это зависит от платформы и является частью "ABI". На самом деле, некоторые компиляторы даже позволяют выбирать между различными соглашениями.
Например, Microsoft Visual Studio предлагает соглашение о вызовах __fastcall, в котором используются регистры. Другие платформы или соглашения о вызовах используют стек исключительно.
Вариативные аргументы работают очень похоже - они передаются через регистры или стек. В случае регистров они обычно располагаются в порядке возрастания, в зависимости от типа. Если у вас есть что-то вроде (int a, int b, float c, int d), ABI PowerPC может поместить a
в r3, b
в r4, d
в r5 и c
в fp1 (I забыл, где начинаются плавающие регистры, но вы поняли).
Возвращаемые значения, опять же, работают так же.
К сожалению, у меня не так много примеров, большая часть моей сборки находится в PowerPC, и все, что вы видите в сборке, это код, идущий прямо к r3, r4, r5, и помещающий возвращаемое значение также в r3.