Smali语法

常用的Smali语法

smali寄存器

在虚拟机Dalvik中,方法中有两种方式定义方法中可以使用的寄存器数量。.registers 指令定义了方法中可以使用的寄存器的总数量。可以选择性的使用.locals ,该指令定义了方法中非参数寄存器的数量。寄存器的总数量应当包括方法参数所使用的寄存器的数量

1
2
3
4
5
6
v字命名 p字命名 说明
v0 the first local register
v1 the sencond local register
v2l p0 the first paramter register
v3 p1 the second parameter register
v4 p2 the third parameter register

指令

赋值指令

move(move destination)。

1
2
3
4
5
6
7
move va,vb #将va=vb
move/from16 va,vb # va=vb va(为8位寄存器) vb(为16位寄存器)
move-result vaa #将上一个invoke类型指令操作的单字非对象结果返回给vaa
move-result-object vaa #将上一个invoke类型指令操作的对象结果返回给vaa
move-exception vaa #保存一个运行时发生的异常到vaa
throw vaa #抛出vaa寄存器的异常

定义指令

数据定义指令用来定义程序中用到的常量、字符串、类等。
基础字节码为const

1
2
3
4
5
6
7
const/4 va,#+b #将数值符号扩展为32位后赋值给寄存器va
const/16 vaa,#+bbbb #将数值符号扩展为32位后赋值给寄存器vaa
const va,#+bbbbbbb #将数值赋值给寄存器va
const/high16 vaa,#+bbbb #将数值右边零扩展为32位后赋值给寄存器vaa
const-wide/16 vaa,#+bbbb #将数值符号扩展为64位后赋值给寄存器vaa
const-string vaa,string@bbb #将字符串赋值给寄存器vaa

跳转指令

跳转指令用于从当前地址跳转到指定的偏移处。Dalvik指令集中有三种跳转指令:无条件跳转(goto),分支跳转(switch)与条件跳转(if)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
goto +AA #无条件跳转到指定偏移处,偏移量AA不能为0。
packed-switch vAA, +BBBBBBBB #分支跳转指令。vAA寄存器为switch分支中需要判断的值BBBBBBBB指向一个packed-switch-payload格式的偏移表,表中的值是有规律递增的。
sparse-switch vAA, +BBBBBBBB #分支跳转指令。vAA寄存器为switch分支中需要判断的值,BBBBBBBB指向一个sparse-switch-payload格式的偏移表,表中的值是无规律的偏移量。
if-eq #如果vA等于vB则跳转。Java语法表示为“if(vA == vB)”
if-ne #如果vA不等于vB则跳转。Java语法表示为“if(vA != vB)”
if-lt #如果vA小于vB则跳转。Java语法表示为“if(vA < vB)”
if-ge #如果vA大于等于vB则跳转。Java语法表示为“if(vA >= vB)”
if-gt #如果vA大于vB则跳转。Java语法表示为“if(vA > vB)”
if-le #如果vA小于等于vB则跳转。Java语法表示为“if(vA <= vB)”
if-eqz #如果vAA为0则跳转。Java语法表示为“if(vAA == 0)”
if-nez #如果vAA不为0则跳转。Java语法表示为“if(vAA != 0)”
if-ltz #如果vAA小于0则跳转。Java语法表示为“if(vAA < 0)”
if-gez #如果vAA大于等于0则跳转。Java语法表示为“if(vAA >= 0)”
if-gtz #如果vAA大于0则跳转。Java语法表示为“if(vAA > 0)”
if-lez #如果vAA小于等于0则跳转。Java语法表示为“if(vAA <= 0)”

比较指令

1
2
cmpl-float #比较两个单精度浮点数。如果vBB寄存器大于vCC寄存器,结果为-1,相等则结果为0,小于的话结果为1
cmpg-float #比较两个单精度浮点数。如果vBB寄存器大于vCC寄存器,则结果为1,相等则结果为0,小于的话结果为-1

四则运算

1
2
3
4
5
6
7
8
9
10
11
add-type #vBB寄存器与vCC寄存器值进行加法运算(vBB + vCC)
sub-type #vBB寄存器与vCC寄存器值进行减法运算(vBB - vCC)
mul-type #vBB寄存器与vCC寄存器值进行乘法运算(vBB * vCC)
div-type #vBB寄存器与vCC寄存器值进行除法运算(vBB / vCC
rem-type #vBB寄存器与vCC寄存器值进行模运算(vBB % vCC)
and-type #vBB寄存器与vCC寄存器值进行与运算(vBB & vCC)
or-type #vBB寄存器与vCC寄存器值进行或运算(vBB | vCC)
xor-type #vBB寄存器与vCC寄存器值进行异或运算(vBB ^ vCC)
shl-type #vBB寄存器值(有符号数)左移vCC位(vBB << vCC )
shr-type #vBB寄存器值(有符号)右移vCC位(vBB >> vCC)
ushr-type #vBB寄存器值(无符号数)右移vCC位(vBB >>> vCC)

smali与java

简单语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.field  定义变量
.method  方法
.parameter  方法参数
.prologue  方法开始
.line 12  此方法位于第12行
const/high16 v0, 0x7fo3 把0x7fo3赋值给v0
invoke-direct  调用函数
return-void  函数返回void
invoke-static  调用静态函数
invoke-super  调用父函数
.end method  函数结束
new-instance  创建实例
iput-object  对象赋值
iget-object  调用对象

java与smali对比

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Smali JAVA
V void
Z boolean
B byte
S short
C char
I int
J long
F float
D double
引用类型
L 对象
[ 数组

先看一个smali代码熟悉下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
java代码
private boolean show(){
boolean tempFlag = ((3-2)==1)? true : false;
if (tempFlag) {
return true;
}else{
return false;
}
}
转换smali代码
.method private show()Z
.locals 2
.prologue //方法开始
.line 22
const/4 v0, 0x1 // v0赋值为1
.line 24
.local v0, tempFlag:Z
if-eqz v0, :cond_0 // 判断v0是否等于0, 不符合条件向下走, 符合条件执行cond_0分支
.line 25
const/4 v1, 0x1 // 符合条件分支
.line 27
:goto_0
return v1
:cond_0
const/4 v1, 0x0 // cond_0分支
goto :goto_0
.end method

smali函数调用

数组:

1
2
3
4
5
6
7
8
整数
I int
[I int[]
[[I int[][]
[[[I int[][]
字符串
[L String

例1:

1
2
3
4
5
6
LpackageName/name/ObjectName;->MethodName(III)Z
MethodName为具体的方法名
(III)Z是方法的签名部分
括号内的III为方法的参数:在此为(int,int,int)
Z表示方法的返回类型:boolean类型

例2:

1
2
3
method(I[[IILjava/lang/String;[Ljava/lang/Object;)Ljava/lang/string
==
String method(int,int[][],int,String,Object)

字段:

1
2
3
Lpackage/name/ObjectName;->FileName:Ljava/lang/String;
类型(Lpackage/name/ObjectName;),字段名(FileName),字段类型(Ljava/lang/String;)

Donate
-------------本文结束感谢您的阅读-------------