Stack Frame (a.k.a Frame)
I had a lot of trouble understanding this, and how it was related to Chunk.
Maybe Ben Eater helps: What is a stack and how does it work?
Implement a Stack in Machine Language
We start to store the stack towards the end of the memory address.
Some Definitions
- The stack pointer is a register that stores the address of the word at the top of the stack (by convention stored at Register 30) (known at runtime)
- The Frame Pointer is a register that stores the memory location of the frame for the currently executing procedure (known at runtime)
- IMPORTANT: Variables are accessed at constant offsets from the address in the frame pointer.
- Frame / Stack frame / activation record = The area of the stack reserved for the variable instances of an invocation of a procedure. the area of memory for values of locals of a procedure invocation
- The Symbol Table maps each local variable in the procedure to a constant offset from the frame pointer (fixed at compile time)
For a stack, variables are accessed at constant offsets from the address in the frame pointer.
Example of how this works in practice with stack frames:
- The program starts execution in
main()
.- The control stack gets a stack frame for
main()
.
- The control stack gets a stack frame for
main()
callsfuncA()
.- A new stack frame for
funcA()
is pushed onto the control stack.
- A new stack frame for
funcA()
callsfuncB()
.- A new stack frame for
funcB()
is added to the control stack.
- A new stack frame for
At this point, the control stack has three stack frames: one for main()
, one for funcA()
, and one for funcB()
. Each function’s context is stored in its respective stack frame.
At Higher level
We have these functions
VarExcess is an abstraction. When it comes to compile, we call eliminateVarAccess
, which does the following:
Loading and Storing Variables (with Stack Frames and Chunk)
As iterated above, we load and store variables using the frame pointer, not the Stack Pointer.
In CS241E , we never push or pop an individual word on the stack at a time. Instead, we organize all memory in Chunks, collections of some known number of words stored at consecutive memory locations. Each Chunk represents a Stack Frame that contains the variables.
We push enough space onto the stack to store a Chunk (which is a stack frame.). Then, to access the variables, we use the symbol table, and load the value with an offset from the base register (Reg.framePointer
) and store that to a target register.
In general, we have something like this:
Push and Pop Stack Operations
The code below is not used in practice, just as a reference to give you a basic idea.
Pushing to the Stack
- Subtract 4 from the stack pointer
- store at the memory address in the new stack pointer
Popping from the Stack
- Load the word from the memory address given by the stack pointer
- Add 4 to the stack pointer (this is the address of the next word on the stack)