Jupp, der Aufrufer kann sich garnicht um sowas kümmern ... woher soll er wissen was wie in der Funktion gemacht wird, und außerdem könnte es sich auch mal ändern.
Aber ja, rein von den Daten ist es schon möglich, dass der Aufrufer bereits Platz auf dem Stack vorbereitet, für alle Parameter in den Registern ... aber wenn, dann wäre es doch eigentlich schwachsinnig "eventuell" nutzlos sowas zu machen, falls es dann doch nicht benutzt wird. Da könnte man auch gleich ALLEs auf den Stack legen und sich das mit den Registern sparen.
Was aber geht, wie man es z.B. unter
Win32 mit den verschiedenen CallingConventions kennt,
* wer den Speicher freigibt, also wer den Stack nach der Ausführung zurücksetzt
meißtens macht es die Funktion, welche normal weiß was sie für Parameter hat,
aber kennt sie es nicht, dann muß es der Aufrufer machen.
-> ein Beispiel sind VarArgs (beim cdecl), wo nur der Aufrufer zu 100% weiß, was er wirklich rein gab.
* oder eben wo und in welcher Reihenfolge die Parameter übergeben werden
-> Register oder ausschließlich auf dem Stack
-> von vorwärts oder rückwärts, bzw. von links nach rechts oder andersrum
So gesehn ist es praktisch, wenn es nur noch eine "offizielle" Variante gibt.
Ja, natürlich kann man dennoch sonstwelchen Mist bauen und es nach belieben machen, aber schon alleine für's Debuggen ist es günstig, wenn es möglichst wenig Vaiationen gibt, weil dann Compilerunabhängig alles gleich analysiert werden kann.