Arm指令

指令集是CPU设计的灵魂,了解指令的作用对于逆向工作来说十分有益。

传输数据指令

CPSR状态寄存器:

条件码标志 保留 控制位
31 30 29 28 27 26 25 24-8 7 6 5 4 3 2 1 0
N Z C V I F T M4 M3 M2 M1 M0
Less than Zero Carry Overflow IRQ FIQ State Mode bits
数据处理指令语法

<操作{<cond>}{S}> <Rd>, <Rn>, <Operand2>

<操作码> <目标寄存器Rd> <第一操作寄存器Rn> <第二操作数Operand2>

第一个位置必须是寄存器,第二操作数可以是寄存器,也可以是立即数

数据传送指令 MOV,MVN

指令的几种形式:

从另一个寄存器、被移位的寄存器或将一个立即数加载到目的寄存器
mov 寄存器、 立即数 mov r0,#0x1 r0 = 0x1
mov 寄存器、 寄存器 mov r2, r1 r2 = r1
取反后再传值,比MOV多了一步取反
mov 寄存器、 立即数 mvn r0,#0x1 r0 = ~0x1
mov 寄存器、 寄存器 mvn r2, r1 r2 = ~r1

movx 其中 x 可以是下面的字符:

l用于32位的长字值
w用于16位的字值 把 16 位立即数放到寄存器的低16位,高16位清0

t用于16位的字值 把 16 位立即数放到寄存器的高16位,低 16位不影响
b用于8位的字节值

算术运算指令 ADD/ADC , SUB/SBC , MUL

ADD

1
2
3
4
5
6
7
8
;ADD加法指令
mov r0, #1
mov r1, #1
add r2, r1, r0  ;r2 = r1 + r0
add r2, r1, #2  ;r2 = r1 + 2
;ADC带进位加法指令,即除了加两个数以外,还要把CPSR的C值也要带进来
ADDS R0,R1,R2; R0=R1+R2,ADDS中S表示把进位结果写入CPSR
ADC R5,R3,R4 ;R5=R3+R4+C

SUB

1
2
3
4
5
6
7
8
;SUB减法指令
mov r0, #5
mov r1, #3
sub r2, r0, r1  ;r2 = r0 - r1
sub r2, r1, #2  ;r2 = r1 - 2
;SBC带进位减法指令,即除了加两个数以外,还要把CPSR的C值也要带进来,类似ADC
SUBS R0,R1,R2; R0=R1-R2,SUBS中S表示把进位结果写入CPSR
SBC R5,R3,R4 ;R5=R3-R4-C

MUL

1
2
3
;MUL 乘法指令
MUL R0,R1,R2; R0=R1*R2
MUL R0,R1,#3 ;R0=R1*3

位操作指令 AND,ORR, TST,BIC

AND 与操作

1
2
AND R0,R1,R2; R0=R1 & R2
AND R0,R1,#0xFF ;R0=R1 & 0xFF

ORR 或操作

1
2
ORR R0,R1,R2; R0=R1 | R2
ORR R0,R1,#0xFF ;R0=R1 | 0xFF

TST 测试某一位是否为1,并把结果写入CPSR,供下一句使用

1
2
TST R1,#0xffe;   等同于if(R1 & 0xffe)
TST R1,#%1;测试最低位是否为1,%表示二进制

BIC 清位操作

1
2
BIC   R0,R0,#0xF          ; 等同于 R0 &=~(0xF)
BIC   R0,R0,#%1011   ; 该指令清除 R0 中的位 0 1  3,其余的位保持;   %表示是二进制,0x表示十六进制

cmp指令

cmp是比较指令,cmp的功能相当于减法指令。它不保存结果,只是影响相应的标志位。其他的指令通过识别这些被影响的标志位来得知比较结果。

cmp指令格式: cmp 操作对象1, 操作对象2

不同大小数进行cmp指令时的结果:

  1. cmp eax, eax (两数相等)

  2. cmp eax, ebx (eax - ebx = 03h)

  3. cmp al, bl (al - bl = -03h)

我们怎么判断大小呢?若执行指令后

(1)ZF

ZF=1 ,则说明两个数相等,因为zero为1说明结果为0。

(2)CF

当无符号时:

CF=1 则说明了有进位或借位,cmp是进行的减操作,故可以看出为借位,所以,此时oprd1 < oprd2

CF=0 则说明了无借位,但此时要注意ZF是否为0,若为0,则说明结果不为0,故此时oprd1>oprd2

当有符号时:

若SF=0,OF=0 则说明了此时的值为正数,没有溢出,可以直观的看出,oprd1>oprd2

若SF=1,OF=0 则说明了此时的值为负数,没有溢出,则为oprd1 < oprd2

若SF=0,OF=1 则说明了此时的值为正数,有溢出,可以看出oprd1 < oprd2

若SF=1,OF=1则说明了此时的值为负数,有溢出,可以看出oprd1 > oprd2

beq & bnq

beq指令

beq指令格式: beq 地址

若标志位ZF为1,则跳转;若为0,则不跳转 (若前面有cmp指令,则意味着相等跳转,不等执行下一步)

bnq指令

bnq指令格式: bnq 地址

若标志位ZF为0,则跳转;若为1,则不跳转 (若前面有cmp指令,则意味着不等跳转,相等执行下一步)

寄存器入栈及出栈指令 POP PUSH

实现低寄存器、可选的 LR 寄存器入栈寄存器、可选的 PC寄存器出栈操作,堆栈地址由 SP 寄存设置,堆栈是满递减堆栈.

指令格式:

1
2
PUSH {reglist[,LR]}               reglist 入栈/出栈低寄存器列表,即 R0~R7        LR 入栈时的可选寄存器
POP {reglist[,PC]} PC 出栈时的可选寄存器

STR指令

STR指令用于从源寄存器中将一个32位的字数据传送到存储器中。

指令格式: STR{条件} 源寄存器,<存储器地址>

1
2
3
STR R0,[R1],#8             ;将R0中的字数据写入以R1为地址的存储器中,并将新地址R1+8写入R1。
STR R0,[R1,#8]             ;将R0中的字数据写入以R1+8为地址的存储器中。”
str     r1, [r0]                       ;将r1寄存器的值,传送到地址值为r0的(存储器)内存中

条件指令

https://www.anquanke.com/post/id/86422

特殊的跟0的比较跳转指令

大于等于0(BGEZ),大于0(BGTZ),小于等于0(BLEZ),还有小于0(BLTZ)

分支指令将一个寄存器的值跟0比较

BEQ,BGE,BGT,BLE,BLT,BNE