7.9.函数运行模拟
\(7.9.\)Run-time Simulation
1.Run-time example
1 | int main() { |
When compiling the
main
part, we:push 3
call factorial
return
1 | function main |
Then we start to compile the function:
- We declare the function.
- We evaluate the condition
n==1
- If the conitional statement returns false, we
push n
, and computefactorial(n - 1)
1 | function factorial(n) |
The pseudo VM code can be translated into these VM codes:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22function main 0
push constant 3
call factorial 1
return
function factorial 0
push argument 0
push constant 1
eq
if-goto BASECASE
push argument 0
push argument 0
push constant 1
sub
call factorial 1
call mult 2
return
label BASECASE
push constant 1
return
Then what happen during the runtime?
main
starts running, and informs that it has 0 local variable.main
pushes, so it starts with an empty stack.push constant 3
, then we get a 3 on the stack.
call factorial 1
, the 1 informs that 1 argument was pushed onto the stack. So we can refer to the topmost value in the stack as argument 0.
2.Callee process
Then we begin to deal with the call
command.
- We first save the frame of
main
onto the stack. Then we jump to executefactorial
.
- The blue dot shows the return address in the given code.
And this is exactly where we want to return to after
factorial
finishes.
- The
eq
consumesargument 0
andconstant 1
, so the overall effect of the first 4 commands on the stack isnil
. - We
push argument 0
,push argument 0
,push constant 1
,sub
, so we are going to get 3 and 2 on the stack.
call factorial 1
, we inform the implementation that 1 argument has been pushed onto the stack, we can refer to it asargument 0
.- We want to issue a
call
command, so the implementation is going to save the frame of the current function, and the return address is the green dot, we save it, too.
- After several calls, we turn to
f(1)
, and the global stack now looks like this:
- This time 1 equals 1, we jump to
BASECASE
,push constant 1
and do areturn
.
When the inplementation encounters the return
command,
it:
- Gets the return address off the stack.
- Copy the return value. In this case, it's
argument 0
, so we copy 1 onarg0
. - After
return
, we can recycle the current frame, which is no more relevant.
And we do this step again and again:
During the process, the caller is completely oblivious of all the drama, it takes part behind the scene.