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

ARM 32位GCC内联汇编原子寄存器对加载/存储约束问题

32位ARM原子寄存器对操作的GCC内联汇编约束问题

指令与寄存器要求

32位ARM汇编中,用于原子加载和存储寄存器对的指令分为两类:

  • ldaexd/stlexd:适配支持获取-释放内存顺序的32位ARMv8架构
  • ldrexd/strexd:适配无内置屏障的ARMv7架构

这类指令对传输寄存器对(Rt和Rt2)有硬性要求:

  • Rt必须是偶数编号寄存器,且不能为LR(链接寄存器)
  • Rt2必须是Rt的下一个寄存器,即R(t+1)

不符合要求的示例代码

以下C/C++内联汇编代码未满足上述寄存器编号规则:

inline static void atomic_exclusive_load_pair_aquire(uint32_t atomic[2], uint32_t target[2])
{
    asm volatile("ldaexd %0, %1, [%2]"  // 原子获取式加载寄存器对
                 : "=r"(target[0]),     // 第一个传输寄存器
                   "=r"(target[1])      // 第二个传输寄存器
                 : "r"(&atomic[0])      // 原子变量基地址寄存器
                 : "memory");           // "memory"作为编译器读写屏障
}

问题

如何通过GCC内联汇编约束描述寄存器对的依赖关系,让编译器自动选择符合规则的寄存器?该方案是否可行?使用“多替代约束”是否是有效解决路径?

解决方案

通过uint64_t类型实现寄存器对的自动映射——在32位ARM平台上,uint64_t会被分配一组偶/奇编号的寄存器对(禁用Thumb模式时符合指令要求)。同时利用GCC半文档化的约束符%Q和%R分别拆分寄存器对的低32位和高32位:

inline static void atomic_exclusive_load_pair_aquire(uint32_t atomic[2], uint32_t transfer[2])
{
    uint64_t pair;
    asm volatile("ldaexd %Q[pair], %R[pair], [%[addr]]"  // 原子获取式加载寄存器对
                 : [pair] "=r"(pair)       // 传输寄存器对
                 : [addr] "r"(&atomic[0])  // 原子变量基地址寄存器
                 :        "memory");       // "memory"作为编译器读写屏障

    transfer[0] = static_cast<uint32_t>(pair);
    transfer[1] = static_cast<uint32_t>(pair >> 32);
}

内容的提问来源于stack exchange,提问作者S. Gleissner

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 04:52:11