ARM和THUMB

ARM 处理器有两种主要的运行状态,ARMThumb,这两种状态和处理器的权限级别没有关系,也就是说,不管是在用户模式还是系统模式下,代码都可能是ARM或Thumb状态。在ARM状态下,处理器使用的是标准的32位ARM指令集。这意味着每条指令都是32位,可以执行复杂的操作。

Thumb状态是ARM处理器的一种16位指令集,设计用来节省内存空间。虽然Thumb指令通常是16位宽,但也可以是32位,取决于具体的指令和操作。Thumb状态下的指令集是ARM状态的子集。以根据需要在这两种状态之间切换。例如,在编写需要嵌入到其他程序中的小型代码片段(如shellcode)时,使用Thumb状态可以更高效地利用内存。

ARMARM公司在不同时间推出了不同版本的Thumb指令集。每个版本可能支持不同的ARM和Thumb指令集变体。并不是所有版本的ARM都支持相同的Thumb指令集。研究的时候具体了解目标设备使用的ARM版本,以及这个版本特别支持的Thumb指令集就可以了。详细信息可以在ARM信息中心查询。

ARM指令简介

前期先了解汇编语言的最小部分如何运行、它们如何相互连接以及通过组合它们可以实现什么目标就可以了,后续在研究过程中逐渐学习即可。

汇编指令模板如下:

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

每个字段的含义如下:

  • MNEMONIC: 助记符,指令名,例如ADD(加法),MOV(移动)
  • {S}: 可选,如果指令中包含S,则表示在执行操作后,处理器的状态标志(如零标志、负数标志、进位标志等)将根据操作结果进行更新。
  • {condition}:可选,条件表达式,指定了指令执行所需的条件。ARM指令可以在满足特定条件时才执行。
  • {Rd}:这是指令执行结果的目标寄存器。指令执行的结果(比如加法操作的和)将被存储在这个寄存器中。Rd代表destination Register(目的寄存器)
  • Operand1:指令的第一个操作数。它可以是一个寄存器的名称或一个立即数(直接给出的数值)
  • Operand2:第二个操作数,可以是一个立即数,或者是一个带有可选移位的寄存器。

几个简单的指令如下:

  • ADD R0, R1, R2:将寄存器R1R2中的内容相加,并将结果存储在寄存器R0

  • ADD R0, R1, #2 : 将寄存器R1中的内容与立即数2相加,并将结果存储在寄存器R0

  • MOV R0, R1, LSL #1:将寄存器R1中的内容逻辑左移一位,然后将结果移动到寄存器R0

  • CMP R0, R1CMP(比较)指令会将寄存器R0R1的值进行比较,根据比较的结果,改变$CPSR中的值

    • 如果R2小于R3,CPSR中的N(负数)标志会被设置为1,表示结果为负
    • 如果R2等于R3,则CPSR中的Z(零)标志会被设置为1,表示结果为零
  • MOVLE R0, #5MOVLE是一种特殊的移动(move)指令,全称是"Move if Less Than or Equal",意思是“如果小于或等于,就移动”,此时会检查上一条指令比较的结果。是否满足“小于等于”,如果满足,那么数字5就会被放入寄存器R0中,如果不满足,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系统调用