在分析一个反编译的ARM二进制文件时,我遇到了这些指令
...
mov r7, #0
uxth r0, r7
...
add r7, r7, #1
uxth r4, r7
...
来自ARM文档:
UXTH{cond} {Rd}, Rm {,rotation}
将16位扩展为32位。它通过:
- 将Rm的值右转0、8、16或24位
- 从得到的值中提取比特[15:0]。
- 0扩展到32位。
这真的让我很困惑,并提出了很多问题:
- mov不能在32位寄存器上运行?
- 使用
uxth
扩展零的目的是什么? - 为什么不直接将值加载到0中?
如果我错了请纠正我,但似乎它只是用0xffff
做AND
。
uxth r4, r7
让我们按顺序应用手册中写的操作。
1。从Rm向右旋转0、8、16或24位
没有设置,所以没有旋转
2。从得到的值中提取比特[15:0]。
3。0扩展到32位
这些步骤加在一起与& 0xffff
相同。
所以基本上它是& 0xffff
以一种不必要的复杂方式写成的。哎呀,即使是编译器也会生成这段代码,所以这似乎是32位ARM中0扩展16位的标准方式。很抱歉误导了你。
mov r7, #0
uxth r0, r7
这些行可能是故意以复杂的方式编写的,或者它来自未优化的编译,或者即使进行了优化,编译器也很糟糕。只要做mov r0, #0
。
莫名其妙地读起来像ux ..
该指令旨在帮助处理16位变量。你的即时动作没有多大意义,但如果我有一个16位的变量在地址0x1001?为了避免未对齐的访问,您希望进行32位加载,然后右移8并使用0x0000FFFF(这会自动给您提供您的符号扩展名)。要做到这一点,通常需要另一个寄存器和几个指令。现在它的两条指令并不一定需要另一个寄存器。在此之前你会看到的是左移16,然后右移以避免寄存器给出掩码和零垫,但这是两个指令。