000: stack ptr ->-->-->-+ (points to "stack frame 2")
--- stack frame 1 |
001: "___ret_pos" |
002: "___p_stack_ptr" |
003: stack var "a" |
004: stack var "b" |
005: stack var "c" |
--- stack frame 2 <----+
006: "___ret_pos"
007: "___p_stack_ptr"
008: stack var "a"
009: stack var "b"
00a: stack var "c"
In order to "set" or "get" var b
(009
) of stack frame 2 we need to take a
look at the stack_ptr
. What we need to do is sPtr' + 'offset
. The offsets
are fully deterministic and are handled by the compiler. In case of var b
of stack frame 2 the offset would be 96 (3*32
). The ASM code for setting
var b
would look like:
PUSH 10 ; push the value
PUSH 0 ; push stack ptr loc
MLOAD ; load stack ptr
PUSH 96 ; push offset
ADD ; get loc of var "b"
MSTORE ; store 10 in address
translates to the following calling routine:
func helloWorld() var {
var b = 10
return "hello world"
}
helloWorld()
Popping a stack (returning) requires the read of __ret_pos
which reads the
location to which we need to jump back and setting the "stack_ptr" to the
current stack's __p_stack_ptr
.
Recursive calling, stack frames
Every time you create a new stack frame, internally, during the compile phase of your compiler, you create a new variable lookup table. You assign an
offset
(starting at= 0
) to each new variable you encounter. Theoffset
variable is used to determine the offset within the calling frame.This means that when you want to load a variable you take the
offset + 2
(+ 2
for the__ret_pos
and__p_stack_ptr
). Loading a variable means that:stack_ptr
loading the beginning of the current stack frame pointing to a memory offsetoffset + 2
The same goes for pointers. When passing pointers around with
&
(something pointing at a variable on a different stack frame) you load the location of memory offset of a previous frame e.g.Translates to