Skip to content

Instantly share code, notes, and snippets.

@obscuren
Last active November 5, 2015 22:31
Show Gist options
  • Save obscuren/f16c6847d65b3763e30e to your computer and use it in GitHub Desktop.
Save obscuren/f16c6847d65b3763e30e to your computer and use it in GitHub Desktop.

Function calling and removing deterministic memory:

Memory and stack management

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.

@obscuren
Copy link
Author

obscuren commented Nov 5, 2015

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. The offset 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:

  1. you load the stack_ptr loading the beginning of the current stack frame pointing to a memory offset
  2. you load the deterministic offset + 2
  3. add the two together and you have the location of the variable.

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.

a := 10
b := &a

Translates to

; sets 10 to "a" like the previous example in the origin post
PUSH 0
MLOAD
PUSH 64
ADD          ; load the pointer (i.e. position in memory)
PUSH0
MLOAD
PUSH 96
ADD
MSTORE  ; store the pointer in "b"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment