GCC下RISC-V内联汇编原子Load/Store报非法操作数错误求解
根本原因
RISC-V指令集架构中,lr.w(加载保留字)、sc.w(条件存储字)属于原子操作指令,其内存操作数仅支持无偏移的基址寄存器寻址格式,也就是只能是(寄存器)的形式,不允许携带立即数偏移。
你原本使用的m是GCC通用内存操作数约束,GCC在生成代码时会自由选择带立即数偏移的寻址方式,报错信息里的lr.w t1,8(a4)、sc.w t0,t1,1048(s0)正是这种情况,不符合lr/sc的指令规范,所以汇编器直接抛出非法操作数错误。
解决方案
你已经找到了正确的方向:使用RISC-V平台GCC专属的A约束替代m约束。A约束的定义就是「仅生成无偏移的内存地址操作数」,完全匹配lr/sc指令的寻址要求。
修改时需要保留输出操作数的=&修饰符:&是early clobber标记,用于告知GCC该输出操作数在汇编块执行完输入操作数之前就会被修改,避免GCC将输入、输出操作数分配到同一个寄存器引发逻辑错误。
修改后完整代码
asm volatile( "als_%=:\n\t" " lr.w.aq t1, %[src]\n\t" " sc.w.rl t0, t1, %[dst]\n\t" " bnez t0, als_%=" : [dst] "=&A" (*((uint32_t*)(0x27402448ULL))) : [src] "A" (*((uint32_t*)(0x000a0018ULL))));
额外说明
如果后续需要在其他场景使用固定地址的内存操作,且对应指令不支持带偏移寻址,都可以优先尝试A约束。你之前测试la指令报错大概率是当时搭配了错误的操作数约束,按上述规则调整约束即可正常运行。
内容的提问来源于stack exchange,提问作者Lance E.T. Compte
相关产品推荐
相关产品推荐

