26

I am trying to understand how stack frames are built and which variables (params) are pushed to stack in what order? Some search results showed that the C/C++ compiler decides based on operations performed within a function. For example, if the function was supposed to just increment a passed-in int value by 1 (similar to ++ operator) and return it, it would put all the parameters of the function and local variables into registers.

I'm wondering which registers are used for returned or pass by value parameters. How are references returned? How does the compiler choose between eax, ebx,ecx and edx?

What do I need to know to understand how registers, stack and heap references are used, built and destroyed during function calls?

4

4 Answers 4

16

In addition to what Dirk said, an important use of stack frames is to save previous values of registers so that they can be restored after a function call. So, even on processors where registers are used for passing parameters, returning a value, and saving the return address, the values of those registers are saved on the stack before a function call so that they can be restored after the call. This allows one function to call another without overwriting its own parameters or forgetting its own return address.

So, calling a function B from function A on a typical "generic" system might involve the following steps:

  • function A:
    • push space for the return value
    • push parameters
    • push the return address
  • jump to the function B
  • function B:
    • push the address of the previous stack frame
    • push values of registers that this function uses (so they can be restored)
    • push space for local variables
    • do the necessary computation
    • restore the registers
    • restore the previous stack frame
    • store the function result
    • jump to the return address
  • function A:
    • pop the parameters
    • pop the return value

This is by no means the only way function calls can work (and I may have a step or two out of order), but it should give you an idea of how the stack is used to let the processor handle nested function calls.

4
  • What does "push" exactly mean here? I have no idea what to make of it. Commented Jan 9, 2017 at 20:12
  • 4
    @TomášZato push and pop are the two fundamental operations on a stack. A stack is a last-in-first-out structure, like a stack of books. When you push, you're putting a new object on top of the stack; when you pop you're taking an object from the top of the stack. You're not allowed to insert or remove objects in the middle, you can only operate on the top of the stack. You might read more about stacks generally and the program stack in particular on Wikipedia.
    – Caleb
    Commented Jan 10, 2017 at 2:49
  • Why would you push address of previous stack frame if you do not use it anywhere in procedure descibed by you? Commented Dec 23, 2020 at 8:47
  • @Trismegistos You push the previous stack frame base pointer so that you can restore it when you're done. The caller needs its stack frame set up just as it was when it made the call, and you can't restore the previous stack frame base pointer if you don't save it somewhere.
    – Caleb
    Commented Dec 23, 2020 at 16:58
12

This depends on the calling convention being used. Whoever defines the calling convention can make this decision however they want.

In the most common calling convention on x86, registers aren't used for passing parameters; the parameters are pushed on to the stack starting with the rightmost parameter. The return value is placed in eax and can use edx if it needs the extra space. References and pointers are both returned in the form of an address in eax.

9

If you understand stack very well then you will understand how memory works in program and if you understand how memory works in program you will understand how function store in program and if you understand how function store in program you will understand how recursive function works and if you understand how recursive function works you will understand how compiler works and if you understand how compiler works your mind will works as compiler and you will debug any program very easily

Let me explain how stack works:

First you have to know how function store in stack :

Heap store dynamic memory allocation values. Stack store automatic allocation and deletion values.

enter image description here

Let's understand with example :

def hello(x):
    if x==1:
        return "op"
    else:
        u=1
        e=12
        s=hello(x-1)
        e+=1
        print(s)
        print(x)
        u+=1
    return e

hello(4)

Now understand parts of this program :

enter image description here

Now let's see what is stack and what are stack parts:

enter image description here

Allocation of the stack :

Remember one thing if any function get “return” no matter it have loaded all his local varibles or anything it will immediately return from stack will his stack frame. It means when any recursive function get base condition and we put return after base condition so base condition will not wait to load local variables which are situated in “else” part of program it will immediately return current frame from the stack and now if one frame return next frame is in activation record. See this in practical:

enter image description here

Deallocation of the block:

So now whenever a function found return statement it delete current frame from the stack.

while returning from the stack value will return in reverse order of order in which they allocated in stack.

enter image description here

These are very short description and if you want to know more deep about stack and double recursion read two post of this blog :

More about stack step by step

More about Double recursion step by step with stack

4

What you are looking for is called Application Binary Interface - ABI.

There is a specification for each compiler that spells out the ABI.

Each platform will usually specify and ABI on order to support interoperability between compilers. For example, x86 Calling Conventions spells out the typical calling conventions for x86 and x86-64. I would expect a more official document than wikipedia however.

Not the answer you're looking for? Browse other questions tagged or ask your own question.