1

如何区分手臂指令和拇指指令?例如:

add r1, r2, r3 ;add r2 and r3, then store the result in r1 register

上述指令在手臂和拇指指令方面如何工作?

4

2 回答 2

2

那么请访问 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 有办法控制它,但它有限制(对于 add 指令))。

添加 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 所以不保存标志所以s 位在编码中为零

所以添加 rd,rn,shifter 操作数,我们从位模式 0b111000I01000 开始,然后 rn 的 4 位 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 指令通常在指令开头使用 0xE 的 ALways 条件,因此如果您看到大量 0xExxxxxxx 形式的 32 位字,则这些字很可能是 arm 指令而不是数据而不是 thumb 指令。纯拇指将有一个不太典型的模式,比如 0x6xxx 和 0x7xxx,但也有所有其他起始值的混合。

于 2012-12-05T15:30:16.533 回答
0

在实践中,没有理由将库编译为 arm,除非您有意选择让一切变得更难。

在 arm 和 thumb 模式之间切换需要一些纳秒,它有硬件支持,顺便说一下,比在内核和用户模式之间切换要快得多。

如果你问我为什么 Google 的整个库都是 arm,我会告诉你,尽管他们应该保持东西向后兼容和一致,但绝对没有理由。

于 2017-05-21T17:27:01.963 回答