DevCN
菜单
全部文章快讯开发深度热点

ARM64 汇编入门:遵守调用约定并实现加法函数

从 C 程序调用一个 ARM64 汇编函数,理解参数寄存器、返回值寄存器和 macOS 符号命名,建立可重复验证的最小跨语言程序。


本节目标

从 C 程序调用一个 ARM64 汇编函数,理解参数寄存器、返回值寄存器和 macOS 符号命名,建立可重复验证的最小跨语言程序。

环境与运行方法

本组限定 Apple Silicon 的 macOS ARM64 与 Clang。保存汇编为 lesson.s,再把下方 C 驱动保存为 main.c,执行 clang -Wall -Wextra -Werror main.c lesson.s -o lesson 后运行 ./lesson。其他架构、操作系统和目标文件格式不能直接照搬符号命名。

C 驱动代码:

#include <stdio.h>
extern long add_minutes(long a, long b);
int main(void) {
    printf("%ld\n", add_minutes(20, 35));
    printf("%ld\n", add_minutes(0, 0));
    return 0;
}

核心思路

在本例使用的 ABI 中,前两个整数参数通过 x0、x1 传入,整数返回值放在 x0。函数只进行加法,不调用其他函数,也不占用栈空间,因此可以直接返回。

完整示例

.text
.globl _add_minutes
.p2align 2
_add_minutes:
    add x0, x0, x1
    ret

预期输出

55
0

逐步理解

全局符号前的下划线是这里的 macOS 目标格式约定,C 中声明时不写下划线。add 把结果写回 x0,ret 按返回地址寄存器回到调用者。对齐指令帮助保持指令地址要求。

这是叶函数,只使用参数和结果寄存器,没有需要保存的被调用者保存寄存器。若进一步调用其他函数或使用这些寄存器,就必须遵守完整保存规则与栈对齐要求。此例不处理溢出检测。

常见问题与边界

  • ARM64 与 x86-64 指令和 ABI 不同。
  • Linux 的符号命名不能直接按本例推断。
  • 寄存器宽度和 C 类型大小需要结合目标 ABI 判断。

动手练习

让 C 驱动调用 add_minutes(-5,35),再增加一组零参数。

参考答案

小范围有符号数的结果为 30,零参数组合按普通加法返回另一值。不要用极端溢出输入推断 C 有符号溢出的通用规则,本例未定义该类业务契约。

DISCUSSION

文章回复

0 条公开回复
未登录回复需要审核后公开
还没有回复,欢迎参与讨论。