理解ARM的第六个指令



在分析一个反编译的ARM二进制文件时,我遇到了这些指令

...
mov r7, #0
uxth r0, r7
...
add r7, r7, #1
uxth r4, r7
...

来自ARM文档:

UXTH{cond} {Rd}, Rm {,rotation}将16位扩展为32位。它通过:

  1. 将Rm的值右转0、8、16或24位
  2. 从得到的值中提取比特[15:0]。
  3. 0扩展到32位。

这真的让我很困惑,并提出了很多问题:

  • mov不能在32位寄存器上运行?
  • 使用uxth扩展零的目的是什么?
  • 为什么不直接将值加载到0中?

如果我错了请纠正我,但似乎它只是用0xffffAND

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,然后右移以避免寄存器给出掩码和零垫,但这是两个指令。

最新更新