【发布时间】:2012-12-05 14:52:46
【问题描述】:
如何区分手臂指令和拇指指令?例如:
add r1, r2, r3 ;add r2 and r3, then store the result in r1 register
上述指令在手臂和拇指指令方面如何工作?
【问题讨论】:
-
你问他们有什么不同吗?或者如果它们不同?或者他们如何做加法?你的实际问题我不清楚。 :-)
标签: arm
如何区分手臂指令和拇指指令?例如:
add r1, r2, r3 ;add r2 and r3, then store the result in r1 register
上述指令在手臂和拇指指令方面如何工作?
【问题讨论】:
标签: arm
请访问 infocenter.arm.com 并获取相关架构的架构参考手册,或者仅获取 ARMv7 手册(不是 -M,而是 -A 或 -R),其中将包含迄今为止的所有指令编码从 ARMv4 到 ARMv7,包括 thumb 和最成熟的 thumb2 扩展。 (您可能需要多个架构参考手册和/或技术参考手册,因为 arm 手册中的指令编码会受到影响)
在 thumb 指令下查看基于寄存器的 ADD 指令,有一种编码,具有三个寄存器编码 T1,它被列为所有 thumb 变体(ARMv4T 到现在(ARMv4T、ARMv5、ARMv6、ARMv7 和可能的 ARMv8))
位 15 到 9 是 0b0001100 rm 的 3 位、rn 的 3 位和 rd 的 3 位(通常 thumb 指令仅限于 r0-r7 需要 3 位进行编码,thumb2 扩展和一些特殊的 thumb 指令允许更高编号寄存器(四位编码))。
该指令在说明中列为 ADDS rd,rn,rm,S 表示保存标志,它来自于衍生 thumb 指令的父 ARM 指令,对于 ARM 指令,您可以选择是否修改标志, thumb 指令你没有(thumb2 有办法控制它,但它有限制(对于添加指令)。
添加 rd,rn,rm
0001100 rm rn rd
所以 ADDS r1,r2,r3 就是这块比特
0001100 011 010 001 = 0001100011010001 = 0001 1000 1101 0001 = 0x18D1
查看 ARM 模式下的 ADD 指令,你从一个条件字段开始,因为你已经写了你的问题,这是一个 ALWAYS 或 1110 模式(总是执行),也因为你写了你写的问题 add not added so not保存标志,因此编码中的 s 位为零
所以添加 rd,rn,shifter 操作数,我们从位模式 0b111000I01000 开始,然后是四个 rn 位 rm 4 位,移位器操作数 11 位。是的,这是一个我位位置 25 不是一个。 I 是移位器操作数编码的一部分
现在转到手册中描述移位器操作数编码的部分。只是一个寄存器 rm 的编码是第 25 位(I 位)为零,11 到 4 为零,3 到 0 为 rm 所以添加 rd,rn,rm
1110 00 0 01000 转 00000 000 转
1110 00 0 01000 0001 0010 00000 000 0011 = 1110 0000 1000 0001 0010 0000 0000 0011 = 0xE0812003
现在我们可以测试一下,拿这个程序
add r1,r2,r3
.thumb
add r1,r2,r3
称它为 add.s 组装然后反汇编
arm-none-eabi-as add.s -o add.o
arm-none-eabi-objdump -D add.o
得到
Disassembly of section .text:
00000000 <.text>:
0: e0821003 add r1, r2, r3
4: 18d1 adds r1, r2, r3
与手编码匹配。
现在,如果您尝试反汇编一大块不知道它们是什么类型的字节,那就另当别论了,这充其量是非常困难的,理想情况下,您希望通过执行和反汇编整个二进制文件模式更改(如果不模拟执行,您可能无法弄清楚)。一条线索是 ARM 指令通常使用 ALways 条件,即指令开头的 0xE,因此如果您看到大量 0xExxxxxxx 形式的 32 位字,则这些字很可能是 arm 指令,而不是数据,而不是 thumb 指令。纯拇指将有一个不太典型的模式,比如 0x6xxx 和 0x7xxx,但也有所有其他起始值的混合。 Thumb2 扩展可以从任一半字边界开始,并且对于 32 位字具有更独特的开始模式,但是因为它们与非 Thumb2 扩展混合并且并不总是在 32 位边界上对齐,所以无论有无 thumb2 扩展,在视觉上都不太容易与数据隔离,只有 ARM 指令易于在视觉上隔离。
【讨论】:
readelf -s add.o,在 .symtab 中你会得到 $a 或 $t 取决于编码,请参阅 sourceware.org/binutils/docs/as/ARM-Mapping-Symbols.html
在实践中,没有理由将库编译为 arm,除非您有意选择让一切变得更难。
在 arm 和 thumb 模式之间切换需要一些纳秒,它有硬件支持,顺便说一下,比在内核模式和用户模式之间切换要快得多。
如果你问我为什么 Google 的整个库都是 arm,我会告诉你,尽管他们应该保持东西向后兼容和一致,但绝对没有理由。
【讨论】: