Confused by return address

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

Confused by return address

riverfish
I'm a bit confused by return address.

...
argument 0
argument n-1
return-address
saved LCL
saved ARG
saved THIS
saved THAT
local 0
local n-1
              <--- SP


This is what the stack looks like just after a function is called but before it's returned.

After it's return, the return value replaces argument 0 in the stack when *ARG = pop() is called.

So what's exactly stored in return address then?

Reply | Threaded
Open this post in threaded view
|

Re: Confused by return address

ybakos
This post was updated on .
Careful, don't confuse the "return value" with the "return address."

Upon returning, the return value of the function should be on the top of the stack, and PC should be set to the return address.

Reply | Threaded
Open this post in threaded view
|

Re: Confused by return address

riverfish
In that case, what does the return address refer to?

I thought after the function is returned, the return value goes where argument 0 is, and SP is set to the next address:

// BEFORE
....
argument 0
argument n-1
return addr
saved LCL
saved ARG
saved THIS
saved THAT
local 0
local n-1
               <---- SP


// AFTER
....
return value
               <---- SP

If so, what's the point of saving return address? Isn't it just easier to set SP to *(argument 0  + 1)?
Reply | Threaded
Open this post in threaded view
|

Re: Confused by return address

ybakos
riverfish, I made a typo: PC should be set to the return address (not SP)

Chew on that and see if it makes sense now.
Reply | Threaded
Open this post in threaded view
|

Re: Confused by return address

riverfish
Sorry bakos, still not making any sense to me!

I'm playing with NestedCall in the VMEmulator.

Inside function Sys.init, it calls Sys.main 0; when it does, the value saved in the 'return address' is 6.

And inside Sys.main, it calls Sys.add12 1; when does, the value saved in the 'return address' is 22.

However, after running the simulation dozens of times I still can't understand the relevancy of these two numbers and how they're used. There doesn't seem to be anything significant stored in either RAM[6] or RAM[22] during this simulation.

If it's suppose to act as a program counter, then doesn't it make logical sense to start at 1 and increment each time a function returns?

Reply | Threaded
Open this post in threaded view
|

Re: Confused by return address

cadet1620
Administrator
First, let me describe how this works in assembly language programs, because that is a published specification. I will describe what I think the VM Emulator does later.

For an assembly language program, program counter means the ROM address of the currently executing instruction. When an ASM program calls a subroutine, the called subroutine needs to know what instruction in the calling program should be jumped to when the called subroutine returns.

For example the ASM code for Sys.init's call to Sys.main might look something like this:
ROM Addr    Code

        // call Sys.main 0
   96       @$RET_ADDR$2
   97       D=A
            ... [ASM code to push D, build the frame, and jump to Sys.main]
  157   ($RET_ADDR$2)
  
        // pop temp 1
  157       @SP
  158       AM=M-1
            ...
In this case, the return address pushed on the stack will be 157, and the return instruction at the end of Sys.main will get that number off the stack and jump to the next instruction in Sys.init.
 

The return addresses pushed on the stack by the VM Emulator are a bit confusing.

In the VM emulator, the program counter is a VM instruction number. Unfortunately, those numbers are not visible to users when the VM Emulator is running. They appear to be a running count of the instructions shown in the "Program" panel.

--Mark
Reply | Threaded
Open this post in threaded view
|

Re: Confused by return address

riverfish
Making sense now and finally got my tests passing. Thanks a lot guys