The primary allocation of memory is done in the _stack arena_.
This arena contains two stacks growing in opposite directions from opposite ends of the arena.
The stack growing from lower memory addresses towards higher addresses is called the "north" stack, while the stack growing from higher to lower addresses is the "south" stack.
Computation begins with a stack frame on the north stack. The current stack frame is delimited by two registers: the stack pointer and the frame pointer.
A stack frame maintains the stack pointer and frame pointer for the previous stack frame as the first two words within the frame, except for the top frame
where these words are null (`0x0`).
Testing whether we are currently in the north or south stack is done by comparing the frame pointer to the stack pointer.
If the frame pointer is greater than the stack pointer, we are in the north stack, otherwise we are in the south stack.
Pushing of a new stack frame is illustrated by the following C-like pseudocode:
```c
void push() {
if(fp > sp)
{
/* we are on the north stack, push on the south stack by reading the end of the last
* south stack frame (the saved frame pointer). If it's null push at the end of the memory arena */
void * new_sp = *(sp + sizeof(void*));
if(new_sp == 0x0) {
new_sp = arena + arena_size - 1;
};
void * new_fp = new_sp - 2 * sizeof(void*);
// save old SP at new SP
// save old FP one word below
*new_sp = sp;
*(new_sp - sizeof(void*)) = fp;
sp = new_sp;
fp = new_fp;
} else {
/* we are on the south stack, push onto the north stack by reading the end of the last
* north stack frame (the saved frame pointer). */
void* new_sp = *(sp - sizeof(void*));
void* new_fp = new_sp + 2 * sizeof(void*);
// Save old SP at new SP
// Save old FP one word above
*new_sp = sp;
*(new_fp + sizeof(void*)) = fp;
sp = new_sp;
fp = new_fp;
}
}
```
Nouns can be pushed onto the stack frame as follows:
```c
// TODO: check that stacks haven't grown into each other
/* Allocate memory on the stack frame for some noun words.
* Note that the parameter is denominated in noun-words, not bytes.
*
* This enables machine-portable code.
void* push_noun(size_t nouns) {
if(fp > sp) { // north stack
// fp is always pointing to free space
base = fp;
fp = fp + nouns * sizeof(void*);
return base;
} else
fp = fp - nouns * sizeof(void*);
// fp is always pointing to free space
base = fp + 1;
return base;
}
}
```
Allocating a cell and receiving it as a noun-word is as follows:
```c
void* push_cell(void* hed, void* tal) {
void* cel = push(2);
*(cel) = hed
*(cel + sizeof(void*)) = tal;
cel = cel >> 2;
cel = cel | (0b11 << (sizeof(void*) - 2));
return cel;
}
```
Pushing an indirect atom is done by providing a pointer to the atom which be copied ot the stack: