The ARM application binary interface (ABI) defines the low-level interface between an application and the ARM processor architecture. It determines how functions are called between an application and the operating system as well as how data is passed between the two. Understanding the ARM ABI is crucial for developing applications that are compatible and optimized for ARM-based systems.
Overview of the ARM ABI
The ARM ABI standardizes how functions are called and data is accessed to enable compatibility between different components in an ARM system. This includes:
- Function calling conventions – Determines how function arguments are passed and return values retrieved.
- Function prolog and epilog – Code executed to set up and teardown function calls.
- Stack organization – How the stack is set up and accessed.
- Register usage conventions – Which registers are preserved across calls and which are volatile.
- Data type alignment – How data structures and variables are aligned in memory.
- Endianness – The byte ordering used for data access.
Following the ABI allows code built with different compilers and libraries to interoperate correctly. This reduces software fragmentation across the ARM ecosystem.
ARM Processor Modes
ARM processors have several execution modes with different purposes:
- User mode – Used for executing normal application code.
- Supervisor mode – Privileged mode for OS kernel and hypervisor.
- Interrupt modes – Entered on interrupts and exceptions.
- Fast interrupt mode – Low latency mode for IO interrupts.
- Abort mode – Entered on memory faults.
- Undefined mode – For undefined instructions.
- System mode – Highest privilege level on ARMv8-A.
The ABI conventions differ between user mode code and privileged code executing in supervisor or system mode.
Function Calling Convention
The ARM ABI specifies how functions make calls and pass arguments in registers or on the stack:
- Registers r0-r3 – Used to pass the first four arguments.
- Stack – Additional arguments are passed on the stack.
- Register r0 – Used to return integer values.
- Registers r0-r1 – Used to return 64-bit integer values.
- Floating point registers s0-s15 – Used to pass floats and doubles.
- Stack pointer (sp) – Points to current stack frame.
For variadic functions, the registers hold the required arguments while extra arguments are pushed onto the stack. This convention enables efficient function calls while supporting flexible argument passing.
Function Prolog and Epilog
ARM code uses standard prolog and epilog sequences when entering and exiting functions:
- Prolog – Save return address and frame pointer, allocate stack frame.
- Epilog – Deallocate stack frame, restore registers, return.
The prolog preserves the return address and sets up the stack by pushing registers. The epilog tears down the stack frame and uses the link register to return.
These sequences encapsulate function calls so that callers and callees can share the stack without interfering with each other’s registers and local variables.
The ARM ABI defines how the stack is structured for function calls:
- The stack grows downwards to lower addresses.
- It must be 8-byte aligned for function calls.
- Arguments and local variables are located below the saved frame pointer.
- The stack pointer (sp) points to the current top of stack.
Following this organization ensures that the stack frames of different functions will be isolated and aligned properly.
Register Usage Conventions
ARM has general purpose registers, floating point registers, and special registers. The ABI specifies conventions for using them:
- r13 – Reserved as stack pointer.
- r14 – Link register to hold return address.
- r15 – Program counter.
- r16-r12 – Temporary registers preserved across calls.
- r0-r3 – Argument passing and return value registers.
- r4-r11 – Temporary registers not preserved across calls.
This convention separates preserved and volatile registers. It enables optimization while supporting subroutine re-entrancy.
Data Type Alignment
The ARM ABI specifies data structure alignment based on data types:
- 8-byte alignment – Double, long long.
- 4-byte alignment – Int, float.
- 2-byte alignment – Short.
- 1-byte alignment – Char, byte.
Because ARM uses aligned load and store instructions, correct data alignment is required for efficient data access.
ARM supports bi-endian operation with runtime configuration:
- Little-endian – Least significant byte has lowest address – used on most ARMv8-A systems.
- Big-endian – Most significant byte has lowest address.
The ABI does not mandate endianness. But data access needs to use the correct endianness for the current system.
User Mode vs Privileged Mode ABI
There are some differences between the ABI conventions in user mode vs privileged modes:
- More registers accessible in privileged modes.
- Banked register sets for interrupt handling.
- Access to special registers for MMU, cache control.
- Differences in stack pointer limits.
- Changes to function prolog/epilog sequences.
This enables the kernel and hypervisor to use features not available in userspace. The user mode ABI is more portable across ARM implementations.
The Power State Coordination Interface (PSCI) defines an ABI for ARM hypervisor services:
- Implemented as SMCCC – Secure Monitor Call
- Provides power management and system control functions
- Used by operating systems to control hardware and cores
- Relies on ARM TrustZone and hypervisor support
Adhering to this ABI enables standardized power management for ARM systems.
The ARM ABI provides standardized conventions for application development on 32-bit and 64-bit ARM platforms. It enables interoperability between components while supporting optimal performance. Following the ARM ABI ensures compatibility across the broad ARM ecosystem.