Naked Function Calls In C++

Hello Everyone! Today we are going to learn about Naked Function Calls in C++. We would have a doubt why the function is call naked in C++. Before, knowing about it we should learn about what a function call is?

Function Call in C++

The process of activating the function and allowing it to run at the place where we require it to be executed in C++ Program is known as Function Call in C++.

There two types of function calls in C++. They are:

  • Function Call with Parameter

Here, in this function call we do assign or pass any parameters to the C++ Program. These Parameters play a crucial role in the running of the program.

  • Functions Call without Parameter

Here, in this function call we do assign or pass any parameters to the C++ Program. These Parameters play a crucial role in the running of the program.

Example

File name: withParameters1. cpp

Example

/* This is a program written to find the factorial of a number using function call which is parameterized or we can say that parameters are passed into the program */

#include <iostream>

#include <cstdio>

using namespace std;

int factorial (int number) 

{

    int i;

    int f=1;

    for(i = 1; i <= number; i++)

    {

        f = f * i;

    }

    return f;

}

int main()

{

    int n;

    cout <<"Enter any number: " << endl;

    cin >>n;

    int fact;

    fact = factorial(n);

    printf("%d is the factorial of %d",fact,n);

    return 0;

}

Input:

Example

Enter any number: 

10

Output:

Output

3628800 is the factorial of 10

Example

File name: withoutParameters1. cpp

Example

/* This is a program written to find the factorial of a number using function call which is not parameterized or no parameter passing */

#include <iostream>

#include <cstdio>

using namespace std;

void factorial () 

{

    int number;

    cout <<"Enter any number: " << endl;

    cin >>number;

    int i;

    int f=1;

    for(i = 1; i <= number; i++)

    {

        f = f * i;

    }

    printf("%d is the factorial of %d",f,number);

}

int main()

{

    

    int fact;

    factorial();

    

    return 0;

}

Input:

Example

Enter any number: 

15

Output:

Output

2004310016 is the factorial of 15

Naked Function Calls

When a function is declared with the naked property, no prolog or epilog code is generated, allowing you to use the inline assembler to create your own unique prolog/epilog sequences.

An advanced feature is the availability of naked functions. They provide you the option to declare a function that is being called from a context other than C or C++, allowing you to base assumptions about the location of parameters or the preservation of registers differently.

Routines like interrupt handlers are examples. The creators of virtual device drivers (VxDs) will find this functionality especially very handy or easy to use.

The naked property is used to specify functions, and when code is generated for such functions, prolog and epilog are not included.

Using inline assembler code, you may utilize this functionality to create your own prolog/epilog code sequences. Writing virtual device drivers makes good use of naked functions. Keep in mind that the x64 platform does not support the naked property; it is only valid on x86 and ARM.

Syntax

Example

_delspec (naked)

Naked functions must utilize extended attribute syntax and the __declspec keyword as the naked attribute only affects a function's declaration and is not a type modifier.

Even if a function is tagged with the __force inline keyword and the naked attribute, the compiler cannot create an inline function for that function.

If the naked attribute is used on anything other than the definition of a non-member method, the compiler throws an error.

Examples

Example

_declspec (naked) float fun ( initial parameters ) { }

			Or

#define Naked _declspec (naked)

Naked float fun ( initial parameters ) { }

Only the nature of the prolog and epilog sequences generated by the compiler is impacted by the naked property.

It has no impact on the code created to invoke these functions. Thus, function pointers cannot contain the naked property since it is not regarded as a component of the type of the function. Additionally, a data definition cannot use the naked property.

Rules and Limitations

Following are the rules and limitations of Naked Function Call in C++:

  • The return keyword cannot be used here in this type of function call
  • _alloca function cannot be used in this type of function calls
  • Initialized local variables are not allowed at function scope to guarantee that no initialization code for local variables enters before the prolog sequence. Particularly, function scope does not allow the definition of C++ objects. A nested scope could, however, include initialized data.
  • Naked Function Calls in C++ must unwind over the stack frame. So, C++ exception handling constructs and structured exception handling are not allowed.
  • Naked Function Calls in C++ must unwind over the stack frame. So, setjmp cannot be used for Naked Function Calls in C++.
  • Every time one of the register parameters for __fastcall bare functions is referenced in C/C++ code, the prolog code should save the value of that register onto the stack location for that variable.
  • If the Naked function call is in lexical scope, C++ class objects cannot be declared. But you are still allowed to define objects in nested blocks.
  • Although it is not advised, the frame pointer optimization (the / Oy compiler option) is automatically suppressed for a naked function.
  • When Naked Function Call building is done with / clr, the naked keyword can be ignored.

Example

Example

// nkdfastcl.cpp

// compile with: /c

// processor: x86

__declspec(naked) int __fastcall  power(int i, int j) {

   // This code is written to calculate the value of x EXOR y, assumes that j >= 0

   // prolog

   __asm {

      push ebp

      mov ebp, esp

      sub esp, __LOCAL_SIZE

// Place ECX and EDX in the x and y stack places.

     mov x, ecx

     mov y, edx

   }

   {

      int s = 1;   // return value

      while (y-- > 0)

         s * = x;

      __asm {

         mov eax, k

      };

   }

   // epilog

   __asm {

      mov esp, ebp

      pop ebp

      ret

   }

}

Ideas to Keep in Mind While Writing Prolog/Epilog Code

It's crucial to comprehend the structure of the stack frame before creating your own prolog and epilog code sequences. Understanding how to utilize the __LOCAL SIZE symbol is also helpful.

Stack Frame Layout

This illustration displays typical prolog code that might be used in a 32-bit function:

Example:

Example

push        ebp                    ; Save ebp

sub         esp, localbytes        ; Allocate space for locals

mov         ebp, esp               ; Set stack frame pointer

push        <registers>      ; Save registers

The "registers" variable is a placeholder for the list of registers that should be saved on the stack, and the "localbytes" variable indicates how many bytes are required on the stack for local variables. You can put any other pertinent data on the stack after pushing the registers. The relevant epilog code is as follows:

Epilog Code

Example

pop         <registers>   ; Restore registers

pop         ebp           ; Restore ebp

mov         esp, ebp      ; Restore stack pointer

ret                       ; Return from function

The stack always becomes smaller (from high to low memory addresses). The pushed value of ebp is where the base pointer (ebp) points. At ebp-4, the residents' region starts. Calculate an offset from ebp by deducting the right amount from ebp in order to access local variables.

LOCAL SIZE

For usage in the inline assembler block of the function prolog code, the compiler supplies a symbol called __LOCAL SIZE. In custom prolog code, this symbol is used to allocate space for local variables on the stack frame.

The value of LOCAL SIZE is set by the compiler. The sum of all user-defined local variables and compiler-generated temporary variables makes up its value. Only as an instantaneous operand, LOCAL SIZE cannot be utilized in an expression. You are not permitted to alter or reinterpret the meaning of this symbol. For instance:

Example

mov        eax, [ebp - __LOCAL_SIZE]   ;Error

mov        eax, __LOCAL_SIZE           ;Immediate operand--Okay

The __LOCAL SIZE symbol is used in the prolog sequence of the naked function that employs unique prolog and epilog sequences as follows:

Example

Example

// the__local_size_symbol.cpp

// processor: x86

__declspec ( naked ) int main() {

   int x;

   int y;

   __asm {      /* prolog */

      push   ebp

      mov      ebp, esp

      sub      esp, __LOCAL_SIZE

      }

   /* Function body */

   __asm {   /* epilog */

      mov      esp, ebp

      pop      ebp

      ret

      }

}

This is all about Naked Function Calls in C++ Language.

Input Required

This code uses input(). Please provide values below: