 In this video, we're going to explain how to pass parameters and return results in subroutines. So the assumption is going to be that we're going to implement a mechanism similar to what a high level programming language would implement when invoking the following line, result equal to function of p1, p2, p3. So let's work with this example. We have a program and within this program function, this function is invoked with three parameters p1, p2, p3 and the result has to be captured back and stored in the variable result. So the scenario that we are considering here is the following. We have the program, few instructions and then at some point there should be some additional instructions in this program to copy the parameters to an area that needs to be defined in that area has to be accessible both by the program and the subroutine. We're going to call this subroutine function as we said and it has its own instructions here, its own calculations and finally we finish when the instruction read. Now as I was saying, the program is going to copy the value of the parameters here with the right several right operations into an area and this area is going to be also accessible to the function such that the function then can read these parameters. After we copy the parameters, we need to call the function, the subroutine and during this calculation as we said, the parameters will be accessed from here but additionally after the calculation is done in the subroutine we need to define another area here which is where we're going to store the result which has to be equally accessible both to the function and the program. Why? Because the function after a while after obtaining the result it will perform a right operation to deposit the result in this location and after returning from the function call there will be some additional instructions in the program to get the result and these instructions of course will perform a read operation over that area. So this is what we're trying to implement here. A mechanism that allows us to create this area where parameters will be written by the invoking program read by the invoked subroutine and another area that is written by the invoking subroutine to deposit the result and read by the invoking program to obtain that result. Now the question is for these two areas that we see here area A and area B, the question is where would you put this? And we have several options and all three of them have been considered by microprocessors, different microprocessors. So the first option is well why don't we choose and select several registers to perform this. In other words we would reserve certain registers to store the parameters used by the function and the parameters expected by the subroutine and we would allocate additional registers to write the results such that the invoking program expects the result there. So this is some sort of pact or agreement between these two entities and we would have to define first predetermining which ones are we using. Then these registers cannot be used for anything else because they are reserved to hold these values and store the result. We also have a problem with the solution is that we have a short number of them, short number of registers. So this is an example with three parameters but what would happen if our function has 15 parameters or even worse in programming language is allowed that we define a function that has a variable number of parameters. So it doesn't work or it works only for very specific cases in which the number of parameters is restricted. We need some alternatives for the cases in which we cannot use all the registers or we have too many parameters. So option number two would be a fixed location in memory. But this has also several issues, right? Because the limitation of a large number of parameters is somewhat solved because we're using memory but what happens for self invoking functions? For self invoking functions we still have a problem because we would need as many copies of these two areas as subroutines are still executing. In other words, if program calls subroutine A, subroutine A calls subroutine B, subroutine B calls subroutine C and so on. For each one of these subroutines that is active we need a memory location holding this parameter and result. And this gets even more complicated when functions invoke themselves when what they call what we call recursive functions. Because then we need as many of these areas as invocations of the functions that are still pending to finish. So as you can see we have here an issue that we need several areas in which to replicate a certain structure which is fixed. How do we solve that? And that is option number three. It is using the stack. So for the stack solution, each invocation, not each subroutine, each time an invocation is performed we allocate an area in the stack to store parameters and result. And this is the solution that has been adopted by most of the microprocessors. What it means is the following. If I have my stack here what it's going to happen is my program it's going to first execute certain instructions to prepare space for the result or reserve space for the result. It's going to position the parameters also in the stack. Let's say p3, p2 and p1. So this would be the equivalent to create parameter and result area right here. After this has been created by the program, then we execute the call and the call would place here the return address. This return address is placed by the call function and is there at the beginning of the execution of the function. So the first instruction of the subroutine will find a stack that has this structure. At the top of it it has the return address and then the parameters and below that the result. Now what happens in this case if the function has local variables? And this is the one of the big advantages of this solution. A local variable in a function behaves very similar or it has a very similar scope if not identical to the parameters and the result. The difference between a local variable and a parameter is just that the parameters start the execution with some specific value given by the calling program whereas the local variables behave as regular variables but their visibility is only active in the execution of the function. So where do you put these local variables? We would repeat the argument saying we could use registers but we only have so many of them. We could use a fixed location, it wouldn't work for recursive functions. Let's put them in the stack. So typically what happens is that you allocate as many slots as you need here and the stack for local variables. So that's it. This slot has been produced by the call. This slot has been produced by the subroutine and this data structure we have in the stack is called the activation. For every subroutine call the program making the function call is when a place is going to place result space and parameters in the top of the stack. The call instruction is going to put the return address on top of the stack and the invoke subroutine is going to place here as much space as needed for the local variables. While the function is performing the computation, a result is obtained and it's placed in this location over here. And finally, by the time the execution finish, we get rid of the local variables. We leave the stack such that the return address is at the top, return is executed, sequence brings us back here and at this point right after the call to the function what we find is a data structure without the return address on top of the stack in which we can find the parameters and obtain the result. And this is the mechanism that is used for subroutine call. Two important features to remember. It is one created per vocation and it supports recursive functions. Why does it support recursive functions? Because once we have an activation block created and we start calculating, making our calculations in a function, if a function has to call itself, it's not a problem because it's going to place parameters and result on top of the stack, return address on top of that, so on and so forth. So what we would have would be different activation blocks on top of each other, waiting in the stack to be destroyed or restored in order opposite in which they were invoked.