Conceptually, call the function. Speciï¬cally: Jump to label, and push the address of this call site onto the call stack.
Conceptually, return from the function. Speciï¬cally: Jump to the instruction immediately after the last call site that was saved on the call stack, and then pop (remove) that address from the call stack. Consider this program, which deï¬nes a function multiply and then computes 2*3*4 by calling multiply twice.
JMP start multiply:
(a): Why did we need CALL? Couldn’t we just JMP to multiply each time we wanted to use it?
(b): Function calling at the assembly level only works if there is a calling convention where the caller and callee agree on where parameters will be passed, and where results will be stored. From looking at the example above, what can you infer about the calling convention? Explain the (apparent) rules for how functions receive their parameters and return their values.
(c): Can you think of any problems or limitations of the calling convention that this code seems to be using?
(d): Draw the call stack as it would look during the execution of the ï¬rst multiply call (i.e. after the ï¬rst CALL, but before the ï¬rst RET). Treat start as a function with zero parameters called at the start of the program, for the purposes of drawing the call stack (even though it isn’t called with CALL).
(e): Draw the call tree showing all function invocations that would happen during the execution of this program. A call tree should have one box (called the activation record) for each time a function was called, along with arrows showing who called who. Again, treat start as a function with zero parameters for this purpose. Extra credit: This implementation of multiply isn’t quite correct, although it works ï¬ne for computing 2*3*4. That doesn’t change what the calling convention or call stack looks like. But for extra credit, explain what’s wrong with it, and provide a correct version that works for all integers.