Function Calling of Factorial Example

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Function Calling of Factorial Example

gnb03
This post was updated on .
Hi,

I have a question regarding the factorial example from lecture 2.5.

I wrote the factorial program from lecture 2.5 in Jack so I could run it in the VM Emulator:

class Main {
        function int main() {
                return Main.factorial(3);
        }
        function int factorial(int n) {
                if (n = 1) {
                        return 1;
                }
                else {
                        return Math.multiply(n, Main.factorial(n-1));
                }
        }
}


I compiled that Jack file using the provided Jack compiler and got this:

1 function Main.main 0
2 push constant 1
3 push constant 3
4 call Main.factorial 1
5 return
6 function Main.factorial 0
7 push argument 0
8 push constant 1
9 eq
10 if-goto IF_TRUE0
11 goto IF_FALSE0
12 label IF_TRUE0
13 push constant 1
14 return
15 goto IF_END0
16 label IF_FALSE0
17 push argument 0
18 push argument 0
19 push constant 1
20 sub
21 call Main.factorial 1
22 call Math.multiply 2
23 return
24 label IF_END0


When I run the VM file in the VMEmulator, I find that RAM[256] is set to 28.


I interpret RAM[256] = 28 to be the return address of bootstrap code 'Call Sys.init'.

This all makes some sense to me because, based on my current understanding of bootstrap code, I think that the VM Emulator implicitly tacks a few lines of VM code to the end of this particular VM program because Sys.init is not explicitly defined.

According to my understanding, this implicit code should include:
'Call Sys.init' // Call Sys.init, which calls Main.main as well as calls other OS functions(the saved, overlapping frames of the latter are seen in RAM[261] - RAM[265]).
'label WHILE' // infinite loop to terminate VM program. This should be the return address of 'Call Sys.init'.
'goto WHILE'
 
I think that 'label WHILE' should be line 28 of the program when taking into account the bootstrap code. Thus, the entire VM program, when taking bootstrap code into account, should look something like this:  

1 function Main.main 0
2 push constant 1
3 push constant 3
4 call Main.factorial 1
5 return
6 function Main.factorial 0
7 push argument 0
8 push constant 1
9 eq
10 if-goto IF_TRUE0
11 goto IF_FALSE0
12 label IF_TRUE0
13 push constant 1
14 return
15 goto IF_END0
16 label IF_FALSE0
17 push argument 0
18 push argument 0
19 push constant 1
20 sub
21 call Main.factorial 1
22 call Math.multiply 2
23 return
24 label IF_END0
25 ???
26 ???
27 call Sys.init 0
28 label WHILE
29 goto WHILE




However, having RAM[256] = 28 is still confusing to me. Even if there are a few extra lines of VM code implicitly tacked on to the VM program, there are not enough lines to make 'label WHILE' line 28.

Could someone explain to me what lines of bootstrap code I am missing here?



Reply | Threaded
Open this post in threaded view
|

Re: Function Calling of Factorial Example

WBahn
Administrator
You are making the mistake of trying to equate a value on the stack in RAM with a VM line number. These are totally separate things.

Consider how many Hack assembly instructions are required for even the simple VM commands. The location of the labels in the ROM will all be much, much higher than the VM line numbers on which they reside.

When you use built-in OS functions, pretty much all bets are off as far as where things will end up or how they will work. The Global Stack and RAM windows in the VM Emulator are really only useful once you are running all of your own code (at which point it can be very useful).

In principle, the VM Emulator is unaware of any details of the underlying hardware. It needs a Global Stack, which could (and arguably should) start at index (as opposed to address) 0. It needs a stack pointer and it needs a means of keeping track of all of the memory segments (including the ones not currently visible) and a means of switching contexts between them. The VM Emulator could (and, again, arguably should) hide all of those details.