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 | ;ADD加法指令 |
SUB
1 | ;SUB减法指令 |
MUL
1 | ;MUL 乘法指令 |
位操作指令 AND,ORR, TST,BIC
AND 与操作
1 | AND R0,R1,R2; R0=R1 & R2 |
ORR 或操作
1 | ORR R0,R1,R2; R0=R1 | R2 |
TST 测试某一位是否为1,并把结果写入CPSR,供下一句使用
1 | TST R1,#0xffe; 等同于if(R1 & 0xffe) |
BIC 清位操作
1 | BIC R0,R0,#0xF ; 等同于 R0 &=~(0xF) |
cmp指令
cmp是比较指令,cmp的功能相当于减法指令。它不保存结果,只是影响相应的标志位。其他的指令通过识别这些被影响的标志位来得知比较结果。
cmp指令格式: cmp 操作对象1, 操作对象2
不同大小数进行cmp指令时的结果:
cmp eax, eax (两数相等)
cmp eax, ebx (eax - ebx = 03h)
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 | PUSH {reglist[,LR]} reglist 入栈/出栈低寄存器列表,即 R0~R7 LR 入栈时的可选寄存器 |
STR指令
STR指令用于从源寄存器中将一个32位的字数据传送到存储器中。
指令格式: STR{条件} 源寄存器,<存储器地址>
1 | STR R0,[R1],#8 ;将R0中的字数据写入以R1为地址的存储器中,并将新地址R1+8写入R1。 |
条件指令
https://www.anquanke.com/post/id/86422
特殊的跟0的比较跳转指令
大于等于0(BGEZ),大于0(BGTZ),小于等于0(BLEZ),还有小于0(BLTZ)
分支指令将一个寄存器的值跟0比较
BEQ,BGE,BGT,BLE,BLT,BNE