Like return addresses, the parameters to a procedure are dynamic data associated with the environment of the procedure. The system stack provides a convenient means of passing and saving parameters during the execution of a procedure.
In the following Pascal code, procedure P is called from the main program with three parameters: A, B and C. Within procedure P, the parameters are the local variables X, Y, and Z.
program Main var A, B, C: integer ; procedure P(X, Y, Z: integer) ; begin { P } { body of P } end ; { P } begin { Main } . . P( A, B, C) ; . . end. { Main }
When using the stack to pass parameters, the parameters are pushed onto the stack by the calling program before the procedure is called. As shown below, parameters A, B, C are pushed on the stack in preparation for calling a procedure:
After the procedure is called, the return address is added to stack by the called procedure:
The parameters are pushed onto the stack one at a time in the following MAL code:
lw $8, A # load A sw $8, ($sp) # push A add $sp, -4 lw $8, B # load B sw $8, ($sp) # push B add $sp, -4 lw $8, C # load C sw $8, ($sp) # push C add $sp, -4 jal P # call procedure P add $sp, 12 # restore stack pointer
After the procedure returns to the calling program, the parameters are removed from the stack by restoring the stack pointer to its original value.
If the parameters are pushed on the stack as group, the stack pointer only needs to be updated once:
add $sp, -12 # make space on stack lw $8, A # load A sw $8, 12($sp) # push A lw $8, B # load B sw $8, 8($sp) # push B lw $8, C # load C sw $8, 4($sp) # push C jal P # call procedure P add $sp, 12 # restore stack pointer
Inside the procedure, the parameters need to be moved from the stack into registers. For example, procedure P might begin as follows:
P: sw $ra, ($sp) add $sp, -4 lw $a0, 16($sp) # load parameter A lw $a1, 12($sp) # load parameter B lw $a2, 8($sp) # load parameter C
Before returning, procedure P must restore register $ra and remove the return address from the stack.