Parameter Passing

Pass by Value
Copy the value onto the stack.  Call the function.  Have the function pop the value from the stack.
Advantages:  No unseen side effects
Disadvantages:  slow for large struct, cannot change args
Pass by Reference
Copy the address of the variable onto the stack.  Call the function.  Have the function pop the address, and use the adress to point to the data to be accessed or changed.
Advantages:  Constant time even for large structs
Disagvantages:  Unseen side effects, what happens if a constant is used.1010
Pass by Value Result.
Copy the address onto the stack.  Call the function.  Have the function pop the address, make a temporary copy, and use that copy for work.  When done, move the copy over the original
Advantages:  No weirdness when aliasing globals, can change args
Disadvantages:  Slow, weird
This code preduces three different answers depending on the type of paramter passing used.
int global = 1;
main() {
    cout << func(global);
}
void func(int a) {
    a++;
    return global+a;
}

Optimizing Parameter Passing

Don't pass the parameters in the stack, use the registers.  Works for a small number of small parameters only.   Caller and Callee must agree on the method.
Any registers used by the caller and the callee must be saved.
Caller Saves:  Need not save stuff not used, must save save code for every call
Callee Saves:  Need not save stuff not overwritten, can have save code only once.
Variable Number of Parameters
 
Caller saves parameters onto stack.Callee decied how many paremeters there are (and what type) generally by looking at the first parameter.  Then pops the rest of the stack.
void foo(char *fmt, ...)
              {
                   va_list ap;
                   int d;
                   char c, *p, *s;

                   va_start(ap, fmt);
                   while (*fmt)
                        switch(*fmt++) {
                        case 's':           /* string */
                             s = va_arg(ap, char *);
                             printf("string %s\n", s);
                             break;
                        case 'd':           /* int */
                             d = va_arg(ap, int);
                             printf("int %d\n", d);
                             break;
                        case 'c':           /* char */
                             c = va_arg(ap, char);
                             printf("char %c\n", c);
                             break;
                        }
                   va_end(ap);
              }