1Learning Outcomes¶
Remember the six fundamental steps to procedure calls.
Differentiate between a caller and a callee.
🎥 Lecture Video
Until 9:10
To round off our discussion of RISC-V, let’s discuss RISC-V implements procedure calls[1].
We first outline the fundamental steps of procedure calls in this section. We then we revisit a few topics in detail:
| Topic | Previous Chapters | This Chapter |
|---|---|---|
| Unconditional Jumps | Usage in branches | General jump instructions |
| Stack Frames | Stack arrays | Pushing/popping stack frames |
| Register conventions | Register names, Register conventions | Calling convention |
Finally, we see some examples of recursive procedures in RISC-V.
2Function Calls in C¶
We begin by developing our intuition about how state changes during a function call in C.
Consider this slightly silly C code. What information must the compiler or programmer keep track of to perform the two mult calls in main?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18int main() { int j = ...; int k = ...; int i = mult(j, k); // first call to mult int m = mult(i, i); // second call to mult } /* very silly mult function with parameters, local variables, and return value */ int mult(int mcand, int mlier) { int product = 0; while (mlier > 0 { product = product + mcand; mlier = mlier - 1; } return product; }
Some notes:
Parameters:
jandkneed to be copied as arguments tomultmultcan access its own local variables (e.g.,product)multshould be able to execute instructionsmultinstructions are located somewhere, andmaininstructions are somewhere elseAfter
multreturns tomain,main’s local variables (e.g.,jandk) should still be there, untouched
2.1House-Sitting Analogy¶
Recall that in our computer layout, there is only one computer with a fixed set of registers. Procedure calls therefore involve “sharing” compute and storage space. When we make a procedure call, we need to keep track of program data (e.g., which local variables belong to whom), procedure control (e.g., which procedure is executing and which is waiting), and parameter passing.
Procedure calls are kind of like house-sitting. Imagine that you have have parents[2] that ask (“call”) you to watch their house for a night.
Set up. Before you arrive, your parents prep some essentials that they know you’ll need; they put these on the table.
Transfer control. Your parents hide the key. They call you over and leave; they also tell you where they hid the key (under the potted plant.)
Prologue. The first thing you do (after unlocking the door) is make space for your stuff. Your parents left some stuff on the table that’s not for you; you put these things in the closet. You know you’re going to use some more things that don’t all fit on the table, so you make some more space in the hallway closet.
Perform the desired task. You watch the pet dog (or cat). Sleep over. Eat dinner. Do homework. Watch TV. Surf the internet.
Epilogue. To clean up, you put your parents’ things from the closet back on the table. You restore the house to the original state (including the closet). You leave them a nice gift, also on the table.
Epilogue: Return control to point of origin. You put the key back in the agreed location (under the potted plant). After you leave, you call your parents telling them to come back.
In this analogy, your parents’ home is the computer. Registers are the table. The closet/garbage/house storage is memory. The essentials your parents prep for you are the arguments. The nice gift you leave is the return value. Your parents are the caller procedure, and you are the callee procedure.
2.2Fundamental Steps¶
We revisit these six fundamental steps in a later section.
Terminology: The RISC-V manual refers to procedure calls and returns, wheras C refers to function calls and returns. For more information, see this Wikipedia page and this C wikibooks page.
Or anyone, really. Imagine this analogy applies to any group of people who call on you to do something for them, and you have to use their property to complete the task. Assume reasonable compensation. :-)