# An attempt at writing a tutorial so that everyone can understand
(please interpret this as markdown, I don't like BBCode)
The stack is used for static memory allocation. Read Wikipedia: https://en.wikipedia...mory_allocation
* When a function need an amount of memory, it decreases the stack pointer (SP) by that many bytes, and own the memory pointed to by SP.
* When a function no longer need that memory, it increases the stack pointer.
### Function call
For the nX/U8 core, when a function calls another functions, the address of the caller is stored in the `LCSR:LR` register, and the arguments are (often) stored into the registers `R0-R15` (and occasionally pushed on the stack, although I can't recall any example right now).
For example, if the function `f` taking 1 1-byte argument in `r2`, has the structure
0:1234 st r2, 08124h
and a snippet of code
0:2466 mov r2, #3
0:2468 bl 0:1234h
0:246c mov r0, #0
is executed, the following will happen:
* At `0:2466`, `r2` is set to decimal value `3`.
* At `0:2468`, when the command `bl 0:1234h` is called,
* The `LCSR:LR` register value is set to `0:246ch` (the address of the command right after the `bl` command) (that is, `LCSR = 0` and `LR = 246ch`)
* The `CSR:PC` register value is set to `0:1234h`.
* Next, `0:1234` is executed.
* After 1 command, at `0:1236`, when the `rt` command is called, the value of `CSR:PC` is set to the value of `LCSR:LR` (which is `0:246ch`).
* Then, the command `0:246ch` is executed.
Ok, next. When a function `a` that is called by another function `parent` needs to call yet another function `child`, it needs to remember the value of `LCSR:LR` when it was called (by `parent`). That is done by the command
which allocates 4 bytes of memory on the stack, and store the value of `lcsr` and `lr` there.
When the function returns, instead of
(which is supposed to return the value of `lr` and `lcsr` and then do the normal return), it executes
For more detailed instruction, read the nX/U8 core instruction manual. But basically, the LR (2 bytes) is on the top, then the LCSR (1 byte), then an unused byte.
Note that, although the CPU allows up to 16 code/data segments, the calculators only uses 2 segments, so only the least significant bit of `lcsr` is important, all other bits are always 0. Moreover because of word alignment of `PC`, the least significant bit of the PC is always zero.
So, how does that help with arbitrary code execution?
As we observed, there are a lot of `pop pc` commands in the code. And those commands set the program counter to whatever on the top of the stack. Therefore, if we executes a `pop pc` command and can control what is in the stack, we can make the PC to jump to arbitrary location.
The remaining problem is to write a program in ROP.
### TODO: Should I add some example programs and explain how they works? I think there are enough programs (scattered in the topic).
### TODO: Is there any unclear part (that you can't understand)?
Edited by user202729, Yesterday, 05:20 PM.