答案在 ARM ARM(ARM 架构参考手册)中。例如,查看 ARM 指令和 Thumb 指令中的 BX。如果这是一个家庭作业问题,还有更多说明。
同时查看伪代码,了解发生异常时会发生什么:
R14_ = 返回链接
SPSR_ = CPSR
CPSR[4:0] = 异常模式编号
CPSR[5] = 0
如果 == 重置或 FIQ 则
CPSR[6] = 1
CPSR[7] = 1
如果 != UNDEF 或 SWI 则
CPSR[8] = 1
CPSR[9] = CP15_reg1_EEbit
PC = 异常向量地址
上述伪代码的 cmets(在 ARM ARM 中)描述了您问题的另一个答案。
现在在 BX 和其他指令描述中不明显且可能误导的地方是 bx rm 并不总是切换状态。 thumb BX 描述说“ARM 代码和 Thumb 代码之间的分支”。好像拇指使用它会带你一直武装代码。伪代码描绘了一幅稍微好一点的画面,寄存器中地址的 lsbit 告诉您是分支到拇指代码还是手臂代码。不过,拇指描述中的 PC 伪代码具有误导性。 Thumb 指令为 16 位,pc 每次向前移动 16 位,0x00、0x02、0x04 等。在 arm 模式下,指令为 32 位,pc 进入 0x00、0x04、0x08 等。(查看分支指令 ARM分支是signed_immed
基本上,如果您有一个混合模式程序,您想使用 BX 而不是 B,特别是在返回 bx lr 而不是 mov pc,lr 时。因此 thumb 和 arm 函数都将使用 bx lr 返回。所有四个案例都包括在内,手臂呼唤臂,手臂呼唤拇指,拇指呼唤臂和拇指呼唤拇指。
因此,请查找影响 cpsr 的 T 位和/或影响程序计数器的指令,这些指令会导致程序计数器在某处分支。还要注意将自己限制在您感兴趣的特定系列/内核(阅读 ARM ARM 时)、armv4t、armv6、armv6 等。您可能想要获取特定内核的 TRM(技术参考手册)使用为好。 ARM ARM 非常通用,随着内核数量的增加,ARM ARM 中的具体差异并不清楚。您需要 TRM。
我有许多 ARM ARM 版本,它们都包含错误/错误。我不知道是有意还是无意,因此总是需要进行一些黑客攻击才能了解您使用的核心是如何工作的。
2018 年编辑
我不会为每个内核等列出一个列表。这就是 arm 文档的用途。
但是,答案再次在于ARM's website 上提供的架构参考手册。您可能不得不牺牲一个电子邮件地址,但非常值得。
您要查找的关键字是interwork 或interworking。旧的/原始的手臂现在称为armv5 architectural reference manual,您可以查找T Flag 并查看哪些指令会更改该标志。对于 armv7-m 和可能的 armv8-m ARM,您可以寻找互通支持或互通地址。它显示了影响PC但支持或不支持互通的指令列表。
对于armv7-a/r,我还在寻找interworking 分支,目前还没有看到一节。寻找在Thumb state 和ARM state 之间的变化,有一个部分显示了从拇指状态到手臂状态的指令列表和从手臂状态到拇指状态的列表。
ARMv6(不是 -M)跨越 armv5 和 armv7 ARM,但每个指令/编码都显示了支持它的体系结构,因此您可能必须遍历每个互通的分支指令和查看它们是否支持 armv6(还显示了 armv4 和 armv5)。尽管在 armv4T/armv5T 中有一个 blx 拇指编码不是 armv6-m/armv7-m 的一部分,但 armv7 手册并不是全部,过去 blx 编码是现在是 thumb2 扩展的一部分。
所有这些都支持的主要指令是BX,其他指令因体系结构而异,取决于您是否可以使用它们来切换状态。如果你正在编写一个模拟器,祝你好运,如果你正在编程,你可以尝试调整架构,但当它怀疑时,只需使用bx。请注意,arm11-mpcore(不是像 Raspberry Pi 中那样的旧 arm11)中存在一个未记录的错误,如果该数据类似于分支指令,则该错误会在 pop pc 或 ldr pc 之后对数据进行预取。
我的建议是不要在 arm11 mpcore 上使用这些指令,而是执行 armv4t 样式的 pop 或加载到 volatile 寄存器和 bx 。 pop {r3}; bx r3 而不是 pop {pc}。副作用很难看到,读取周期可能发生在执行读取操作的外围设备上,例如从 uart 上的数据寄存器读取并丢失字符。仅供参考,我们花了一段时间才找到并确认这一点。