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

ARM GNU工具链中如何在汇编常量内对符号执行位运算?

解决GNU汇编中ARM Cortex-M4向量表符号位运算的汇编器报错问题

我在为Cortex-M4编写ARM固件,使用GNU工具链创建向量表时,编写了如下汇编代码:

MY_VECTOR_TABLE:
  .long 0                        // SP Init
  .long SYMBOL_TO_HANDLER1 | +1l // Reset
  .long SYMBOL_TO_HANDLER2 & -2l // NMI
...

但汇编器抛出错误:

Error: invalid operands (MY_SECTION_NAME and ABS sections) for |' Error: invalid operands (*MY_SECTION_NAME* and *ABS* sections) for &'

原因很明确:符号的最终地址要到链接阶段才能确定,汇编器无法将位运算编码进可重定位目标文件——只有加减运算能被汇编器通过重定位条目记录,位运算做不到。由于Cortex-M4仅支持Thumb指令,Thumb例程地址的bit[0]必须置位,禁用的中断则需要设为0,但向量表存在内存映射的Flash中,无法在运行时修改,也不想手动编辑二进制镜像,以下是可行的解决方法:

方法1:通过链接器脚本处理位运算

在链接器脚本中定义经过位运算处理后的符号,然后在汇编代码中直接引用这些符号:

链接器脚本添加内容:

SYMBOL_TO_HANDLER1_THUMB = SYMBOL_TO_HANDLER1 | 1;
SYMBOL_TO_HANDLER2_DISABLED = SYMBOL_TO_HANDLER2 & ~1;

修改后的汇编代码:

MY_VECTOR_TABLE:
  .long 0                        // SP Init
  .long SYMBOL_TO_HANDLER1_THUMB // Reset
  .long SYMBOL_TO_HANDLER2_DISABLED // NMI
...

链接器在链接阶段已经掌握所有符号的最终地址,完全支持对可重定位符号执行位运算。

方法2:用汇编.set伪指令结合链接器表达式

直接在汇编代码中通过.set定义包含位运算的符号,这些运算会延迟到链接阶段执行:

.set SYMBOL_TO_HANDLER1_THUMB, SYMBOL_TO_HANDLER1 | 1
.set SYMBOL_TO_HANDLER2_DISABLED, SYMBOL_TO_HANDLER2 & -2

MY_VECTOR_TABLE:
  .long 0                        // SP Init
  .long SYMBOL_TO_HANDLER1_THUMB // Reset
  .long SYMBOL_TO_HANDLER2_DISABLED // NMI
...

GNU汇编器允许在.set中使用链接器可解析的表达式,这样就绕过了汇编阶段无法处理位运算的限制。

方法3:利用Thumb函数的自动位0置位特性

如果SYMBOL_TO_HANDLER1是用-mthumb编译的Thumb函数,GNU工具链会自动在函数符号的地址中置位bit0,此时直接写.long SYMBOL_TO_HANDLER1即可,无需手动|1。而对于需要禁用的中断(比如NMI),直接写.long 0即可,不需要对无效符号做&-2操作。

内容的提问来源于stack exchange,提问作者Echelon X-Ray

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 00:22:08