You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apple Silicon ARM64环境下jmp_buf存储寄存器及SDK注释疑问

Apple Silicon Mac 中 jmp_buf 寄存器存储的疑问与验证方法

在Apple Silicon Macbook上编写原生协程时,需要用到setjmp.h中的jmp_buf保存上下文,因此需要明确jmp_buf中具体存储哪些寄存器。查看MacOSX 13.3 SDK中的setjmp.h文件时,发现代码注释与宏定义存在矛盾。

存在矛盾的SDK代码

/*
 * _JBLEN is the number of ints required to save the following:
 * r21-r29, sp, fp, lr == 12 registers, 8 bytes each. d8-d15
 * are another 8 registers, each 8 bytes long. (aapcs64 specifies
 * that only 64-bit versions of FP registers need to be saved).
 * Finally, two 8-byte fields for signal handling purposes.
 */
#define _JBLEN      ((14 + 8 + 2) * 2)

typedef int jmp_buf[_JBLEN];
typedef int sigjmp_buf[_JBLEN + 1];

#else
#   error Undefined platform for setjmp
#endif

宏_JBLEN定义为((14 + 8 + 2) * 2),但注释中称是12个通用寄存器加8个浮点寄存器。根据ARM64架构资料,x19-x28是被调用者保存寄存器(共10个),加上x29(fp)、x30(lr)、x31(sp)、pc,总共14个通用寄存器,这与宏中的14对应。疑惑是注释错误还是自身计算有误?另外,如何准确确定jmp_buf中存储的寄存器?若MacOSX SDK的注释确实错误,该如何修正?


一、注释错误的确认

注释确实存在错误:

  • 注释里的r21-r29, sp, fp, lr == 12 registers描述有误:
    1. ARM64架构下,被调用者保存的通用寄存器是x19-x28(共10个),而非r21-r29(这是ARM32的寄存器命名规则);
    2. 加上x29(fp)、x30(lr)、x31(sp)、pc(程序计数器),总共14个通用寄存器,这与宏定义中的14完全对应;
    3. 注释中“12个寄存器”的说法错误,实际应为14个通用寄存器。

二、准确确定jmp_buf存储寄存器的方法

  • 查看苹果开源libc代码:苹果会开源系统级组件代码,ARM64架构下的setjmp实现(通常在libc/arm64目录下的setjmp.s等汇编文件)会明确写出哪些寄存器被写入jmp_buf,是最权威的参考。
  • 调试对比验证:编写简单测试程序,先读取被调用者保存寄存器(如x19-x28、fp、lr)的值,调用setjmp保存上下文后,打印jmp_buf的内容,对比寄存器值与jmp_buf中对应位置的数据,即可确定每个位置对应的寄存器。
  • 参考AAPCS64规范:Apple Silicon遵循ARM的AAPCS64规范,其中明确要求setjmp需要保存被调用者保存的通用寄存器、d8-d15浮点寄存器(被调用者保存的浮点寄存器),以及信号处理相关字段,这与代码中注释提到的d8-d15和信号字段的描述一致。

三、SDK注释的修正方式

  • 本地修改(仅供个人参考):直接修改本地SDK中的setjmp.h文件,将注释中的错误内容替换为正确描述:
    * x19-x28, sp, fp, lr, pc == 14 registers, 8 bytes each. d8-d15
    
  • 避免影响系统编译:更稳妥的方式是不修改系统SDK文件,而是在自己的项目中添加备注说明该注释错误,或者复制一份修正后的头文件到项目本地,仅在自己的代码中引用。

内容的提问来源于stack exchange,提问作者Edenlia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 03:12:44