ARM汇编中的编码寄存器操作数是如何实现的?

3

我反编译了一些ARM ELF文件并读取了汇编代码。但是,我不知道一些代码如何被翻译成助记符。例如,我得到了以下代码:

#hex code | #mnemonic             | #binary
0xb480    | push {r7}             | 1011 0100 1000 0000
0xb580    | push {r7, lr}         | 1011 0101 1000 0000
0xb5f0    | push {r4,r5,r6,r7,lr} | 1011 0101 1111 0000

因此,您可以清楚地看到push的操作码为0xb40xb5(如果推送多个值)。但是如何创建寄存器列表呢?

第一个示例非常清晰,r7由第8位编码,即置位。但是,为什么第二个操作码也会推送lr?难道没有相应的标志位吗?


你确定操作码是两个完整字节吗?它可能只有6/7位。 - hivert
2个回答

6

PUSH指令在Thumb模式下有三种编码方式。第一种编码方式长度为16位,自ARMv4T(原始的Thumb实现)开始存在:

15141312|11|109|8|      7..0    |
 1 0 1 1| 0| 10|M| register_list|

由于register_list只有8位,因此它只能推送寄存器R0R7(如果设置了M位,则还可以推送LR)。

在Thumb-2(ARMv6T2、ARMv7及更高版本)中,又添加了两个编码。它们都是32位长:

1514131211|109|876|5|4|3210||151413|    12 .. 0    |
 1 1 1 0 1| 00|100|1|0|1101|| 0 M 0| register_list |

在这个例子中,register_list 有13位,所以它可以将R0R12LR推入堆栈。
我不会列举第三种编码,但它可以推入任何单个寄存器。
顺便说一下,POP编码非常相似。
16位POP:
15141312|11|109|8|      7..0    |
 1 0 1 1| 1| 10|P| register_list|

可以将 R0R7PC(位于 P)弹出。

POP 多个 32 位寄存器:

1514131211|109|876|5|4|3210||151413|    12 .. 0    |
 1 1 1 0 1| 00|010|1|0|1101|| P M 0| register_list |

可以将R0R12PC(位于P上)和LR(位于M上)推入栈中。


0
据我所知,16位Thumb指令PUSH只能推送低8个寄存器(R0-R7),LR是例外。0xB480和0xB580之间的不同位是该指令的push_LR_register位...
15 14 13 12 11 10 09 08 07 06 05 04 03 02 01
 1  0  1  1  0  1  0  R  L  L  L  L  L  L  L

这里标记为 L 的位是寄存器列表 <0-7>。标记为 R 的位保留给LR寄存器...


在我的指令集PDF中,它写道:“Push Multiple Registers将R0-R12和LR寄存器的子集(或可能全部)存储到堆栈中。” http://web.eecs.umich.edu/~prabal/teaching/eecs373-f10/readings/ARMv7-M_ARM.pdf 因此,可能是标有M的位是“LR”寄存器吗? - reox
1
@reox:是的,在编码 T1 中,M 是 LR 寄存器的位。我在早期的 PDF 文件中看到过... - Malkocoglu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接