Search code examples
cassemblykeil

Stop Keil uvision from pushing registers on function call


When I call a C function containing an infinite loop from main() it pushes some registers on the stack before executing that function. And since the function contains an infinite loop, those registers never gets popped.

Here's an example,

void My_Func (void)
{   
    int flag_1 = 1;

    while(1)
    {       
        if(counter > 5 && flag_1)
        {
            flag_1 = 0;
        }

        else if(counter > 550 && flag_1)
        {
            flag_1 = 0;
        }
   }    
}


int main(void)
{
    My_Func();

    return 0;
}

Here counter is a global variable.

When I call My_Func() it pushes R4, R5, R6 before executing the function. The disassembly looks like this,

0x080004BC B470      PUSH     {r4-r6}

And then the function execution starts. But since there is an infinite loop inside the function the registers never gets popped.

Is there any way to stop KEIL IDE from pushing registers before executing function, without modifying the function definition?


Solution

  • You can use the __attribute__((noreturn)) on the function declaration to inform the compiler that the function won't be returning. According to the Arm Keil documentation this attribute is described as:

    9.41 __attribute__((noreturn)) function attribute Informs the compiler that the function does not return. The compiler can then perform optimizations by removing code that is never reached.

    Usage Use this attribute to reduce the cost of calling a function that never returns, such as exit(). Best practice is to always terminate non-returning functions with while(1);.

    This should prevent the compiler from generating the function prologue code that pushes the registers R4 to R6.