How does function call work?

Sayali Ayarkar
4 min readApr 17, 2021

Prerequisites :

  • You should have knowledge about any programming language, c language would be better
  • You should know about registers in microprocessor such as Stack Pointer(SP), Link Register(LR), Program counter(PC) and RISC architecture

Introduction

Well, we create a function to do some operations and we need to call them in order to use it. A simple function would look as follows :

int add(int a, int b)//return type integer, function name add, parameters a and b with data type integer
{
int sum = 0;sum = a + b;//it adds two integer values and store it in sum variablereturn sum;//return integer sum}

So, whenever we want to add two integers, we pass parameters in this function like this: add(1,3) and the result of this function we can store in some other variable or directly print. That’s how a simple function call works.

But what exactly happens in the background?

Function call working

There is a term called Calling Convention. It is an implementation-level scheme that describes how a function should receive parameters and how it should return value. There are a number of variations in calling conventions depending on system architecture. Some architecture uses registers, some uses stack, and some uses both.

First, I’ll explain working in simple terms without mentioning any registers.

Suppose function_1 is calling function_2 then your stack will look like this:

When Function call occurs following way stack would be filled:

Local variables of function_1 would be pushed if there are any in the same order.

If function_2 requires any parameters then they would be pushed on to the stack in reverse order.

Return Address would be pushed. It would jump to function_2.

After jumping to the function_2 local variables would be pushed on to the stack.

While returning from Function call following way the stack would be cleared:

  1. The local variables of function_2 would be cleared from stack
  2. After getting the return address and it would go back to that location
  3. Perform whatever the next instruction is.

Let’s see how registers are part of this process.

Here, I’ll be referring to ARM cortex-M3 processor which uses 32-bit architecture. It uses the load-store architecture that means data on external memory is been accessed by explicit instructions. Other ALU operations are done only on registers. ARM cortex-M3 has 15 registers. R0-R12 are general-purpose registers and R13–R15 are special-purpose registers.

LR(R13) is the link register used to hold the return address for a function call.
SP(R14) is the stack pointer that always points to the top of the stack.
PC(R15) is the program counter which tracks the instructions which it is about to execute next.
(R4-R11) contains local variables.
(R0-R3) contains arguments that are passed through the function and the result which is returned from callee function. The Callee function is the function that is called.

In normal operations, variables are stored in registers and the processor does operations using values of these registers according to the instructions given.

In a function call, registers values can be modified. Hence to preserve these values of caller function for using them at a later stage, they are pushed onto the stack before jumping to the callee function.

Whenever we call a function, LR gets updated with return address and PC gets the address of a callee function. After that local variables from R4–R11 pushed onto the stack memory. Then arguments from R0-R3 were pushed onto the stack. The function return address from LR would be pushed on the stack. After jumping to the callee function, R4-R11 will be updated with local variables and arguments which are passed through that function.

After execution of function if it needs to return a value then that return value would be stored in R0.

While returning to the caller function, pop out the return address and update the PC. After returning to the caller function, R4-R11 would be pulled from the stack and that particular memory location from the stack would be cleared.

This is how function call works. Thanks for reading .. :)
Let me know your feedback :)

--

--