我反编译了一些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
的操作码是0xb4
或0xb5
。但是,如何创建寄存器列表?
第一个例子非常清楚,r7
由第8位编码,该位被设置。但是,为什么第二个操作码也会推动lr
?那个没有标志吗?
答案 0 :(得分:5)
Thumb模式下有PUSH
指令的三种编码。第一个是16位长并且自ARMv4T(原始Thumb实现)以来存在:
15141312|11|109|8| 7..0 |
1 0 1 1| 0| 10|M| register_list|
由于register_list
是8位,因此如果设置了R0
位,它只能将寄存器R7
推送到LR
(和M
。
在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位,因此可以将R0
推送到R12
和LR
。
我不会列出第三个编码,但它可以推送任何一个寄存器。
BTW,POP
编码非常相似。
16位POP
:
15141312|11|109|8| 7..0 |
1 0 1 1| 1| 10|P| register_list|
可以R0
到R7
和PC
(位P
)。
32位POP
倍数:
1514131211|109|876|5|4|3210||151413| 12 .. 0 |
1 1 1 0 1| 00|010|1|0|1101|| P M 0| register_list |
可以R0
到R12
,PC
(位P
)和LR
(位M
)。
答案 1 :(得分:0)
AFAIR,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的位是register_list< 0-7>。标记为R的位保留用于LR寄存器......