文章目录

  • ARM & Thumb
  • ARM和Thumb之间的区别:
  • ARM指令简介


ARM & Thumb

 ARM处理器有两种主要状态可以运行(ARM和Thumb)(在这里不包括Jazelle)。这些状态与特权级别无关。例如,以SVC模式运行的代码可以是ARM或Thumb。这两种状态之间的主要区别是指令集,其中ARM状态下的指令始终为32位Thumb状态下的指令为16位(但可以为32位)。知道何时以及如何使用Thumb对于我们的ARM利用开发目的尤其重要。在编写ARM shellcode时,我们需要摆脱NULL字节,而使用16位Thumb指令而不是32位ARM指令会减少使用它们的机会。

 ARM版本的调用约定不仅令人困惑,而且并非所有ARM版本都支持相同的Thumb指令集。在某个时候,ARM引入了增强的Thumb指令集(伪名:Thumbv2),该指令集允许32位Thumb指令甚至条件执行,而在此之前的版本中是不可能的。为了在Thumb状态下使用条件执行,引入了“ it”指令。但是,此指令在以后的版本中被删除,并交换了一些本应使事情变得不那么复杂的东西,但是却达到了相反的目的。我不知道在所有不同的ARM版本中ARM / Thumb指令集的所有不同变体,老实说我不在乎。你也不应该 您唯一需要知道的是目标设备的ARM版本及其特定的Thumb支持,以便您可以调整代码。ARM信息中心应帮助您确定ARM版本的详细信息(http://infocenter.arm.com/help/index.jsp)。

 如前所述,有不同的Thumb版本。不同的命名只是为了使它们彼此区分(处理器本身始终将其称为Thumb)。

  • Thumb-1(16位指令):在ARMv6和更早的体系结构中使用。
  • Thumb-2(16位和32位指令):通过添加更多指令并使它们的宽度为16位或32位(ARMv6T2,ARMv7)来扩展Thumb-1。
  • ThumbEE:包括一些针对动态生成的代码(在执行之前或执行期间在设备上编译的代码)的更改和添加。

ARM和Thumb之间的区别:

  • 条件执行:ARM状态下的所有指令均支持条件执行。某些ARM处理器版本允许使用IT指令在Thumb中有条件执行。有条件的执行导致更高的代码密度,因为它减少了要执行的指令数量并减少了昂贵的分支指令数量。
  • 32位ARM和Thumb指令:32位Thumb指令带有.w后缀。
  • 桶形移位器是ARM模式的另一个独特功能。它可以用于将多个指令缩小为一个。例如,您可以使用左移1-> Mov R1,R0,LSL,而不是使用两条指令进行乘法运算(将寄存器乘以2并使用MOV将结果存储到另一个寄存器中),而不是在MOV指令中包含乘法#1; R1 = R0 * 2

要切换处理器执行的状态,必须满足以下两个条件之一:

  • 我们可以使用分支指令BX(分支和交换)或BLX(分支,链接和交换)并将目标寄存器的最低有效位设置为1。这可以通过在偏移量上加1来实现,例如0x5530 + 1。可能会认为这将导致对齐问题,因为指令是2字节或4字节对齐的。这不是问题,因为处理器将忽略最低有效位。有关更多详细信息,请参见 第6部分:条件执行和分支。
  • 我们知道,如果当前程序状态寄存器中的T位置1,则我们处于Thumb模式。

ARM指令简介

 这部分的目的是简要介绍ARM的指令集及其一般用法。对于我们而言,至关重要的是要了解最小的汇编语言是如何工作的,它们如何相互连接以及将它们组合起来可以实现什么。

 如前所述,汇编语言由指令组成,而指令是主要的构建块。ARM指令通常后跟一个或两个操作数,并且通常使用以下模板:

MNEMONIC {S} {condition} {Rd},Operand1,Operand2

 由于ARM指令集的灵活性,并非所有指令都使用模板中提供的所有字段。但是,模板中字段的用途描述如下:

MNEMONIC     -指令的简称(助记符)
{S}          -可选的后缀。如果指定了S,则根据操作结果更新条件标志
{condition}  -执行指令需要满足的条件
{Rd}         -用于存储指令结果的寄存器(目标)
Operand1     -第一个操作数。寄存器或立即值
Operand2     -第二个(灵活的)操作数。可以是立即数(数字)或带可选移位的寄存器

 虽然MNEMONIC,S,Rd和Operand1字段很简单,但condition和Operand2字段需要更多说明。条件字段与CPSR寄存器的值紧密相关,或者确切地说,与寄存器内特定位的值紧密相关。Operand2之所以称为灵活操作数,是因为我们可以以各种形式使用它-作为立即值(具有有限的一组值),寄存器或带移位的寄存器。例如,我们可以将这些表达式用作Operand2:

#123      -立即值(一组有限的值)。 
Rx         -寄存器x(如R1,R2,R3 ...)
Rx,ASR n  -寄存器x算术右移n位(1 = n = 32)
Rx,LSL n  -逻辑x左移n位的寄存器x(0 = n = 31)
Rx,LSR n  -寄存器x的逻辑右移n位(1 = n = 32)
Rx,ROR n  -向右旋转n位的寄存器x(1 = n = 31)
Rx,RRX    -寄存器x向右旋转一位,扩展

 作为一个简短的示例,说明了不同种类的指令的外观,让我们看一下以下列表。

ADD   R0, R1, R2       -将R1(Operand1)和R2(Operand2以寄存器形式)的内容相加并将结果存储到R0(Rd)中
ADD   R0, R1, #2       -将R1(Operand1)和值2(Operand2以立即值形式)的内容相加并将结果存储到R0(Rd)中
MOVLE R0, #5           -仅在满足条件LE(小于或等于)的情况下,将数字5(Operand2,因为编译器将其视为MOVLE R0,R0,#5)移动到R0(Rd)。
MOV   R0, R1, LSL #1   -将R1的内容(逻辑左移的寄存器形式的操作数2)左移一位至R0(Rd)。因此,如果R1的值为2,则将其左移一位并变为4。然后将4移至R0。

 作为一个简短的摘要,让我们看一下将在以后的示例中使用的最常见的说明。

操作说明

描述

操作说明

描述

MOV

移动数据

EOR

按位异或

MVN

移动并取反

LDR

加载

ADD

加法

STR

储存

SUB

减法

LDM

加载多个

MUL

乘法

STM

储存多个

LSL

逻辑左移

PUSH

推入堆栈

LSR

逻辑右移

POP

弹出堆栈

ASR

算术右移

B

分支

ROR

右旋

BL

分支使用链接

CMP

比较

BX

分支与交换

AND

按位与

BLX

分支使用链接和交换

ORR

按位或

SWI / SVC

系统调用