ARM Thumb中恒非零寄存器上CBZ指令的作用问询
Flashforge固件中ARM Thumb冗余CBZ指令的分析
我在用Ghidra分析Flashforge 3D打印机固件时,发现一段ARM Thumb代码:
... LAB_0012a734: XREF[2]: 0012a808(j), 0012a810(j) 0012a734 06 9b ldr r3,[sp,#local_18] 0012a736 a3 f1 0c 00 sub.w r0,r3,#0xc 0012a73a a0 42 cmp r0,r4 0012a73c 69 d1 bne LAB_0012a812 ... ... LAB_0012a806: XREF[1]: 0012a85a(j) 0012a806 00 2a cmp r2,#0x0 0012a808 94 dc bgt LAB_0012a734 0012a80a 05 a9 add r1,sp,#0x14 0012a80c f9 f6 f6 ea blx <EXTERNAL>::std::basic_string<char,std::char_t 0012a810 90 e7 b LAB_0012a734 LAB_0012a812: XREF[1]: 0012a73c(j) 0012a812 43 f2 40 72 movw r2,#0x3740 0012a816 c0 f2 02 02 movt r2,#0x2 0012a81a 8a b1 cbz r2,LAB_0012a840 0012a81c 04 3b subs r3,#0x4 0012a81e bf f3 5f 8f dmb #0x1f LAB_0012a822: XREF[1]: 0012a82e(j) 0012a822 53 e8 00 2f ldrex r2,[r3,#0x0] 0012a826 51 1e subs r1,r2,#0x1 0012a828 43 e8 00 14 strex r4,r1,[r3,#0x0] 0012a82c 00 2c cmp r4,#0x0 0012a82e f8 d1 bne LAB_0012a822 0012a830 bf f3 5f 8f dmb #0x1f ...
其中0012a81a处的cbz指令会在r2为0时跳转到LAB_0012a840,但r2通过12a812/12a816处的movw/movt指令被赋值为0x23740,且无分支跳过这些赋值步骤,代码也非自修改,经调试确认r2永不为0。针对该指令的作用,主要有以下几种可能性:
冗余的空指针防护代码:这是最合理的解释。这段代码大概率由C/C++编译器自动生成——即便开发者明确知晓指针不会为空,编译器的默认安全配置(或开启了特定安全编译选项)仍会插入空指针检查,用于防御潜在的未定义行为。比如源码中对应的指针变量未被标记为非空属性(如
__attribute__((nonnull))),编译器就会生成这类检查指令。代码迭代残留产物:可能是代码重构或优化过程中留下的冗余指令。例如原本逻辑中r2存在为0的分支,后续开发者修改逻辑移除了该分支,但编译器未彻底优化掉对应的检查;或是不同编译环境的产物——Debug版本会保留更多安全检查,而最终固件虽为Release版本,部分检查仍未被清理。
反汇编误解析的小概率情况:虽然你已调试确认r2不会为0,仍可再验证
movw+movt的赋值是否确实得到0x23740,以及是否存在异常、硬件触发的上下文切换等隐藏逻辑可能修改r2。但根据你的描述,这种可能性极低。
内容的提问来源于stack exchange,提问作者w_m0zart
相关产品推荐
相关产品推荐

