GCC/GAS中LDR Rd,=带取反常量表达式的用法问题
解决GNU ARM工具链中
ldr伪指令复杂常量表达式解析问题 问题分析
GNU的ARM汇编器对ldr r0, =<expr>中的表达式支持有限,无法像Ride7那样直接在=后处理带取反、位或的组合表达式,但可以通过预计算、指令拆分或宏封装的方式解决。
解决方法
方法1:提前定义组合常量
在.equ段直接预计算好目标掩码,后续直接引用即可:
.equ BIT_30, 1 << 30 .equ BIT_27, 1 << 27 .equ BIT_25, 1 << 25 .equ BIT_5, 1 << 5 .equ MASK_TARGET, ~(BIT_30 | BIT_27 | BIT_25 | BIT_5) ; 直接使用预定义常量 ldr r0, =MASK_TARGET
GNU汇编器会在预处理阶段完成.equ中的表达式计算,生成合法常量供ldr伪指令调用。
方法2:用MVN指令替代取反逻辑
如果目标值可以通过ARM原生指令实现,无需存入常量池,可拆分指令完成:
; 先加载需要取反的原掩码 ldr r1, =(BIT_30 | BIT_27 | BIT_25 | BIT_5) ; 对r1取反后存入r0 mvn r0, r1
若原掩码符合ARM立即数编码规则,还能进一步优化为:
mov r1, #(BIT_30 | BIT_27 | BIT_25 | BIT_5) mvn r0, r1
方法3:宏封装简化重复调用
如果需要多次使用这类复杂掩码,可定义宏自动处理表达式计算:
.macro LDR_NOT reg, mask_expr .equ __TEMP_MASK, ~(\mask_expr) ldr \reg, =__TEMP_MASK .endm ; 调用示例 LDR_NOT r0, (BIT_30 | BIT_27 | BIT_25 | BIT_5)
宏会在汇编阶段自动展开并完成表达式计算,生成合法的ldr指令。
编译验证
使用上述方法后,需确保:
.equ定义的位掩码为合法32位整数- 表达式运算符优先级正确(必要时加括号)
- 目标ARM架构支持对应指令(
MVN为通用ARM指令,无架构限制)
内容的提问来源于stack exchange,提问作者jozi
相关产品推荐
相关产品推荐

