ARM Thumb模式下构建跳转表:标签差值表达式范围可靠校验方法问询
ARM Thumb模式下跳转表标签差值的范围校验方案
问题说明
在ARM Thumb模式下使用tbb指令构建跳转表时,跳转表的每个字节项必须满足(目标标签 - .Ltable)/2的结果处于0~255区间,才能保证tbb指令正确执行。但当前汇编器的原生校验能力不足:
- GNU汇编器(GAS)仅校验值在-128~255之间,无法确保偏移为非负数
- Clang的汇编器完全不做任何范围校验
此前有一段仅适配GAS的校验代码,但无法在Clang下生效:
.byte -((foofoo1-.Ltable)/2)*(foofoo1>.Ltable) + (foofoo1<=.Ltable)*100000
可靠的跨编译器校验方法
1. 通用断言实现(兼容GAS与Clang)
使用汇编器标准的.assert伪指令,可在编译阶段直接检查偏移范围,超出时抛出明确错误:
tbb [pc, r1] .Ltable: .assert ((foofoo1-.Ltable)/2) >= 0 && ((foofoo1-.Ltable)/2) <= 255, "foofoo1的跳转偏移超出tbb指令有效范围(0~255)" .byte (foofoo1-.Ltable)/2 .assert ((foofoo2-.Ltable)/2) >= 0 && ((foofoo2-.Ltable)/2) <= 255, "foofoo2的跳转偏移超出tbb指令有效范围(0~255)" .byte (foofoo2-.Ltable)/2
.assert在GAS和Clang中均受支持,能统一实现严格的范围校验,避免运行时因偏移非法导致的错误。
2. GAS专属的更灵活校验
若仅针对GAS环境,可使用.if伪指令实现更复杂的校验逻辑,错误提示更直观:
tbb [pc, r1] .Ltable: .if ((foofoo1-.Ltable)/2) < 0 .error "foofoo1位于跳转表之前,偏移为负数,不符合tbb要求" .endif .if ((foofoo1-.Ltable)/2) > 255 .error "foofoo1与跳转表的距离过远,偏移超过255,不符合tbb要求" .endif .byte (foofoo1-.Ltable)/2
关于编译器自有校验的确认
当通过高级语言(如C)生成Thumb模式的跳转表时,主流编译器(GCC/Clang)会自动处理tbb指令的偏移合法性:
- 若
switch语句的分支目标偏移符合tbb要求,编译器会生成tbb跳转表 - 若偏移超出范围,编译器会自动切换为其他跳转实现(如直接分支指令),或抛出编译错误
但手写汇编代码时,编译器/汇编器不会主动进行这类校验,必须手动添加上述断言逻辑来保障正确性。
内容的提问来源于stack exchange,提问作者David Monniaux
相关产品推荐
相关产品推荐

