WinCE 和 Linux 上的 ARM 调用约定

linuxoperating systemopen source更新于 2026/2/8 21:52:17

简介

ARM 处理器架构因其低功耗、高性能和低成本的特点,在嵌入式系统和移动设备中越来越受欢迎。它广泛应用于 Windows CE 和 Linux 等操作系统的开发。本文将讨论 Windows CE 和 Linux 上的 ARM 调用约定。

什么是调用约定?

调用约定是一组规定程序中函数调用方式的规则。这些规则用于定义如何传递参数、如何处理返回值以及在函数调用期间如何管理堆栈。ARM 架构有几种不同的调用约定,它们因所使用的操作系统而异。

Windows CE 上的调用约定

Windows CE 是一款专为手机和 PDA 等小型设备设计的实时操作系统。 Windows CE 中使用的 ARM 调用约定称为"Windows CE 操作系统的 ARM 过程调用标准"(APCS-CE)。

APCS-CE 为函数调用定义了几条规则。首先,函数的前四个参数传递到寄存器 r0 至 r3。如果参数超过四个,则通过堆栈传递。其次,函数的返回值传递到寄存器 r0。如果返回值大于 32 位,则传递到寄存器 r0 和 r1。

第三,堆栈以特定方式管理。调用函数时,调用者负责将返回地址压入堆栈。被调用者负责将剩余的寄存器内容压入堆栈,然后才能使用它们。最后,堆栈按 8 字节对齐。

示例

以下是一个使用 APCS-CE 调用约定对两个数字进行加法运算的函数示例 -

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; 
}

在此示例中,add() 函数接受两个参数(a 和 b)并返回它们的和。参数传递到寄存器 r0 和 r1,并使用 bl 指令进行函数调用。sum() 函数单独定义,接受两个参数(a 和 b),并将这两个参数相加后返回。

Linux 上的调用约定

Linux 是一种流行的开源操作系统,可在各种设备上运行,包括服务器、台式机和嵌入式系统。Linux 中使用的 ARM 调用约定称为 ARM 过程调用标准 (APCS)。

APCS 为函数调用定义了几条规则。首先,函数的前四个参数传递到寄存器 r0 到 r3。如果参数超过四个,则通过堆栈传递。其次,函数的返回值传递到寄存器 r0。如果返回值大于 32 位,则将其传入寄存器 r0 和 r1。

第三,堆栈以特定方式管理。函数调用时,调用者负责将返回地址压入堆栈。被调用者负责在使用剩余寄存器之前将其压入堆栈。最后,堆栈按 8 字节对齐。

示例

以下是一个使用 APCS 调用约定对两个数字进行加法运算的函数示例 -

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" : "= ) }

在此示例中,add() 函数接受两个参数(a 和 b)并返回它们的和。参数传递到寄存器 r0 和 r1,并使用 bl 指令进行函数调用。sum() 函数单独定义,接受两个参数(a 和 b),并将这两个参数相加后返回。

APCS-CE 与 APCS 之间的差异

APCS-CE 与 APCS 之间的主要差异在于堆栈的管理方式。APCS-CE 要求堆栈对齐 8 字节,而 APCS 没有此要求。此外,APCS-CE 要求调用者在调用函数之前将剩余寄存器压入堆栈,而 APCS 没有此要求。

另一个差异在于返回值的处理方式。APCS-CE 要求将返回值传递到寄存器 r0,而 APCS 允许将返回值传递到任何寄存器。

此外,需要注意的是,调用约定可能因所使用的编译器而异。例如,不同版本的 GCC 可能针对同一操作系统使用不同的调用约定。请务必查阅所用编译器的文档,以确保遵循正确的调用约定。

另一个重要的考虑因素是,ARM 架构同时支持 32 位和 64 位模式,并且调用约定会根据所使用的模式而有所不同。例如,在 64 位模式下,参数通过寄存器 x0 到 x7 传递,而不是通过 r0 到 r7 传递。

最后,值得注意的是,除了 APCS 和 APCS-CE 之外,ARM 架构还有许多其他调用约定。例如,Microsoft Visual C++ 编译器生成的 ARM 代码有调用约定,LLVM 编译器生成的 ARM 代码也有调用约定。

结论

在本文中,我们讨论了 Windows CE 和 Linux 上的 ARM 调用约定。我们已经看到,这两个操作系统都使用 ARM 过程调用标准,但在堆栈管理和返回值处理方式上存在一些差异。理解这些调用约定对于在 ARM 架构上编写高效且可移植的代码至关重要。


相关文章


有用资源