ARM calling conventions on WinCE and Linux


Introduction

The architecture of ARM processor has become increasingly popular in embedded systems and mobile devices due to its low power consumption, high performance, and low cost. It is widely used in development of operating systems such as Windows CE and Linux. In this article, we will be discussing ARM calling conventions on Windows CE and Linux.

What is a Calling Convention?

A calling convention is a set of rules that dictate how function calls are made in a program. These rules are used to define how arguments are passed, how return value is handled, and how stack is managed during function call. There are several different calling conventions for ARM architecture, and they vary depending on operating system being used.

Calling Conventions on Windows CE

Windows CE is a real-time operating system designed for small devices such as mobile phones and PDAs. ARM calling convention used in Windows CE is called ARM Procedure Call Standard for Windows CE Operating System (APCS-CE).

APCS-CE defines several rules for function call. Firstly, first four arguments of a function are passed in registers r0 to r3. If there are more than four arguments, they are passed on stack. Secondly, return value of function is passed in register r0. If return value is larger than 32 bits, it is passed in registers r0 and r1.

Thirdly, stack is managed in a specific way. When a function is called, caller is responsible for pushing return address onto stack. callee is responsible for pushing remaining registers onto stack before it can use them. Finally, stack is aligned to 8 bytes.

Example 

Here is an example of a function that adds two numbers using APCS-CE calling convention −

int add(int a, int b) { 
   int c; 
   __asm { 
      mov r0, a 
      mov r1, b 
      bl sum 
      mov c, r0 
   } 
   return c; 
}
int sum(int a, int b) { 
   return a + b; 
}

In this example, add() function takes two arguments (a and b) and returns their sum. arguments are passed in registers r0 and r1, and function call is made using bl instruction. sum() function is defined separately and takes two arguments (a and b), which are added together and returned.

Calling Conventions on Linux

Linux is a popular open-source operating system that runs on a wide range of devices, including servers, desktops, and embedded systems. ARM calling convention used in Linux is called ARM Procedure Call Standard (APCS).

The APCS defines several rules for function call. Firstly, first four arguments of a function are passed in registers r0 to r3. If there are more than four arguments, they are passed on stack. Secondly, return value of function is passed in register r0. If return value is larger than 32 bits, it is passed in registers r0 and r1.

Thirdly, stack is managed in a specific way. When a function is called, caller is responsible for pushing return address onto stack. callee is responsible for pushing remaining registers onto stack before it can use them. Finally, stack is aligned to 8 bytes.

Example 

Here is an example of a function that adds two numbers using APCS calling convention −

int add(int a, int b) { 
   int c; 
   asm volatile ( 
      "mov r0, %1
\t" "mov r1, %2
\t" "bl sum
\t" "mov %0, r0
\t" : "= ) }

In this example, add() function takes two arguments (a and b) and returns their sum. arguments are passed in registers r0 and r1, and function call is made using bl instruction. sum() function is defined separately and takes two arguments (a and b), which are added together and returned.

Differences between APCS-CE and APCS

The main difference between APCS-CE and APCS is way in which stack is managed. APCS-CE requires that stack be aligned to 8 bytes, while APCS does not have this requirement. Additionally, APCS-CE requires caller to push remaining registers onto stack before calling function, while APCS does not have this requirement.

Another difference is way in which return value is handled. APCS-CE requires that return value be passed in register r0, while APCS allows return value to be passed in any register.

Additionally, it is important to note that calling conventions can vary depending on compiler being used. For example, different versions of GCC may use different calling conventions for same operating system. It is important to consult documentation for specific compiler being used to ensure that correct calling convention is being followed.

Another important consideration is that ARM architecture supports both 32-bit and 64-bit modes, and calling conventions can vary depending on which mode is being used. For example, in 64-bit mode, arguments are passed in registers x0 to x7 instead of r0 to r7.

Finally, it is worth noting that ARM architecture has a number of other calling conventions beyond APCS and APCS-CE. For example, there is a calling convention for ARM code generated by Microsoft Visual C++ compiler, as well as a calling convention for ARM code generated by LLVM compiler.

Conclusion

In this article, we have discussed ARM calling conventions on Windows CE and Linux. We have seen that both operating systems use ARM Procedure Call Standard, but there are some differences in way in which stack is managed and return value is handled. Understanding these calling conventions is important for writing efficient and portable code on ARM architecture.

Updated on: 14-Mar-2023

242 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements