(assuming x86) First you need to understand the stack . Functions use a region of memory called the "stack". You can think of it as a stack of plates, where each plate contains a DWORD (32 bit) of data. The CPU has a register that keeps track of the current location on the stack (it’s just a virtual memory address) that we are dealing with. It is called a stack pointer and is usually stored in the esp register.
When functions interact with the stack, they usually perform one of two tasks: push or pop . A “push” is what it puts on top of the stack, which consists of moving the stack pointer to the next highest position and then copying something to a new location (new top). The push “increases the stack” because more data is stored there (more records).
“Pop” is when the “top” item on the stack is “deleted”, which consists of copying what is currently on top of the stack (indicated by the esp register) into the processor register (usually eax) and then moving the stack pointer one position lower on the stack.
So now we can talk about setting up a function call.
code
tB(3, 4);
Knot
When a call occurs, we transfer the context from the current function to the called function. The information about additional elements that the function should execute is the arguments that we push onto the stack.
Now the new function will work with the storage to free up space for local variables, as well as save the stack pointer in the register so that it can be returned after the function returns. If this did not happen, then the calling function would be completely disoriented when it regains control, having no idea how to access the materials that it previously put on the stack, for example, to its own local variables or context for the stack pointer for which summoned him.
Now this is happening in the assembly (steal it from Havendar).
I am sure there are some details that I forgot, especially when returning from function B, but this is a pretty good overview, I think.
source share