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 有符号溢出的通用规则,本例未定义该类业务契约。
文章回复
0 条公开回复