Smali语法
数据类型
Byte | B |
| Boolean | Z |
Short | S |
| Long | J |
Char | C |
| Java对象 | L |
Int | I |
| 数组 | [ |
Float | F |
|
|
|
Double | D |
|
|
|
void | V |
|
|
|
· invoke-static 是类静态方法的调用,编译时,静态确定的;
· invoke-virtual 虚方法调用,调用的方法运行时确认实际调用,和实例引用的实际对象有关,动态确认的,一般是带有修饰符protected或public的方法;
· invoke-direct 没有被覆盖方法的调用,即不用动态根据实例所引用的调用,编译时,静态确认的,一般是private或<init>方法;
· invoke-super 直接调用父类的虚方法,编译时,静态确认的。
· invokeinterface 调用接口方法,调用的方法运行时确认实际调用,即会在运行时才确定一个实现此接口的对象。
方法定义 Func-Name(Para-Type1Para-Type2Para-Type3...)Return-Type
java | samli |
void foo() | foo ()V |
boolean foo(int a, int b, int c) | foo (III)Z |
String foo (Boolean isB, int[] arrA, int[] arrB, String strA, long c·) | foo (Z[I[ILjava/lang/String;J)Ljava/lang/String; |
|
|
类定义
subObjectName | LpackageName/objectName; |
objectName.subObjectName //内部类 | LpackageName/objectName$subObjectName; |
class WMWActivity | .class public Lcom/disney/WMW/WMWActivity; |
extends BaseActivity | .super Lcom/disney/common/BaseActivity; |
implements IBurstyAdListener | .implements Lcom/burstly/lib/ui/IBurstlyAdListener; |
@MemberClasses{} | .annotation system Ldalvik/annotation/MemberClasses; Value={} .end annotation |
上面定义的static fields和instance fields均为成员变量,格式是:.fieldpublic/private [static] [final] varName:<类型>。然而static fields和instance fields还是有区别的,当然区别很明显,那就是static fields是static的,而instance则不是。根据这个区别来获取这些不同的成员变量时也有不同的指令。一般来说,获取的指令有:iget、sget、iget-boolean、sget-boolean、iget-object、sget-object等,操作的指令有:iput、sput、iput-boolean、sput-boolean、iput-object、sput-object等。没有“-object”后缀的表示操作的成员变量对象是基本数据类型,带“-object”表示操作的成员变量是对象类型,特别地,boolean类型则使用带“-boolean”的指令操作。
成员变量定义
private static final String PARAM_ID=“id”; | .field private static final PRARM_ID:Ljava/lang/String; = “id” |
private String _activityPackageName; | .field private _activityPackageName:Ljava/lang/String; |
|
|
|
|
函数
private static int sum(int a, int b) { return a+b; } | #以.method 开头 ,以.end method 结尾,声明作用域方式与java一样, #括号内的字母代表参数,括号后的参数代表返回类型 .method private static sum(II)I .locals 4 #表示需要申请4个本地寄存器 .parameter #这里表示有两个参数 p0 .parameter #这里表示有两个参数 p1 .prologue #函数开始 .line 27 #空行 move v0, p0 .local v0, a:I move v1, p1 .local v1, b:I move v2, v0 move v3, v1 add-int/2addr v2, v3 move v0, v2 .end local v0 #a:I return v0 .end method |
操作符(vx寄存器vy寄存器简称:vx,vy)
Opcode name | 说明 | 案例 |
nop | 无操作 | 0000 - nop |
move vx,vy | 将vy赋值给vx 256寄存器 |
|
Move/from16 vx,vy | 将vy(int)赋值给vx 当vy是64k寄存器 |
|
move/16 |
|
|
move-wide |
|
|
move-wide/from16 vx,vy | 将vy(long,double)赋值给vx 当vy是64k寄存器 |
|
move-object vx,vy | 将vy(值对象)赋值给vx |
|
move-object/from16 vx,vy | 将vy(值对象)赋值给vx 当vy是64k寄存器 |
|
move-object/16 |
|
|
move-result vx | 将前一个调用方法的返回值(int)赋值给vx |
|
move-result-wide vx | 将前一个调用方法的返回值(double,long)赋值给vx |
|
move-result-object vx | 将前一个调用方法的返回值(值对象)赋值给vx |
|
move-exception vx | 将方法执行抛出的异常对象地址赋值到 vx |
|
return-void | 返回空 |
|
return vx | 返回 int |
|
return-wide vx | 返回 double/long |
|
return-object vx | 返回对象地址 |
|
const/4 vx,lit4 | 将长度4位的数值赋值给vx | Const/4 vx, 0x2 |
const/16 vx,lit16 | 将长度16位的数值赋值给vx | Const/16 vx,ox16 |
const vx, lit32 | 将int型数值赋值给vx | Const vx,ox231 |
const-wide/16 vx, lit16 | 将int型数值赋值给vx和vx+1,扩展成long型 |
|
const-wide/32 vx, lit32 | 将32位数值赋值给vx和vx+1,扩展成long型 |
|
const-wide vx, lit64 | 将64位数值赋值给vx和vx+1,扩展成long型 |
|
const/high16 v0, lit16 | 将16位数值赋值到vo寄存器中最高的16位,初始化 |
|
const-wide/high16 vx,lit16 | 将16位数值赋值到vx和vx+1中最高的16位,初始化 |
|
const-string vx,string_id | 将string常量赋值给vx |
|
const-string-jumbo |
|
|
const-class vx,type_id | 将类的类型的地址赋值给vx |
|
monitor-enter vx | 加锁 |
|
monitor-exit | 释放锁 |
|
Check-cast vx type_id | 检查vx里的对象能不能强转成某个类的对象,否则抛异常 |
|
instance-of vx,vy,type_id | 如果vy的对象是指定类的实例则设vx值为非零 |
|
array-length vx,vy | 计算array vy的长度并赋值给vx |
|
new-instance vx,type | 将指定的类实例化并将地址赋值给vx |
|
new-array vx,vy,type_id | 实例化指定类型且长度为vy的array并将地址赋值给vx |
|
filled-new-array {parameters},type_id | 实例化指定类型的空间并且将parameter的元素全部填充,但是这种方式不安全。 |
|
filled-new-array-range {vx..vy},type_id | 实例化指定类型的空间并且将vx到vy(连续的)的元素全部填充,但是这种方式不安全。 |
|
fill-array-data vx,array_data_offset |
|
|
throw vx | 将异常对象vx抛出 |
|
goto target | 无条件跳转 short |
|
goto/16 target | 无条件跳转 16位 |
|
goto/32 target | 无条件跳转 32位 |
|
packed-switch vx,table | 对应switch语句,vx代表case序号(连续) |
|
sparse-switch vx,table | 对应switch语句,vx代表case序号(少量) |
|
cmpg-float vx, vy, vz | If(vy>vz&&vy>0||vy==vz&&vz<0||vy<vz 赋值到vx |
|
cmpl-double vx,vy,vz | 同上(vy和vy+1与vz和vz+1对比) |
|
cmpg-double vx, vy, vz | 同上 |
|
cmp-long vx, vy, vz | 同上 |
|
if-eq vx,vy,target | vx==vy |
|
if-ne vx,vy,target | vx!=vy |
|
if-lt vx,vy,target | vx<vy |
|
if-ge vx, vy,target | Vx>=vy |
|
if-gt vx,vy,target | Vx>vy |
|
if-le vx,vy,target | Vx<vy |
|
if-eqz vx,target | Vx==0 |
|
if-nez vx,target | Vx!=0 |
|
if-ltz vx,target | Vx<0 |
|
if-gez vx,target | Vx>=0 |
|
if-gtz vx,target | Vx>0 |
|
if-lez vx,target | Vx<=0 |
|
aget vx,vy,vz | 将array vy的第vz个(int)值赋值给vx |
|
aget-wide vx,vy,vz | 将array vy的第vz个(long,double)值赋值给vx |
|
aget-object vx,vy,vz | 将array vy的第vz个(对象地址)值赋值给vx |
|
aget-byte vx,vy,vz |
|
|
aget-char vx, vy,vz |
|
|
aget-short vx,vy,vz |
|
|
aput vx,vy,vz | 将vx值赋值给array vy的第vz个(int) |
|
aput-wide vx,vy,vz |
|
|
aput-objectvx,vy,vz |
|
|
aput-booleanvx,vy,vz |
|
|
aput- byte,vy,vz |
|
|
aput-char vx,vy,vz |
|
|
iget vx, vy, field_id | 将vy对象的指定字段赋值给vx | iget v0, v1, Test2.i6:I |
iget-wide vx,vy,field_id |
|
|
iget-object vx,vy,field_id |
|
|
iget-boolean vx,vy,field_id |
|
|
iget-byte vx,vy,field_id |
|
|
iget-char vx,vy,field_id |
|
|
iget-short vx,vy,field_id |
|
|
iput vx,vy, field_id | 将vx 赋值给vy对象的指定字段 | iput v0,v2, Test2.i6:I |
iput-wide vx,vy, field_id |
|
|
iput-object vx,vy,field_id |
|
|
iput-boolean vx,vy, field_id |
|
|
iput-byte vx,vy,field_id |
|
|
iput-char vx,vy,field_id |
|
|
iput-short vx,vy,field_id |
|
|
sget vx,field_id | 读取指定静态字段到vx | sget v0, Test3.is1:I |
sget-wide vx, field_id |
|
|
sget-object vx,field_id |
|
|
sget-boolean vx,field_id |
|
|
sget-byte vx,field_id |
|
|
sget-char vx,field_id |
|
|
sget-short vx,field_id |
|
|
sput vx, field_id | 将vx赋值给指定的静态字段 | sput v0, Test2.i5:I |
sput-wide vx, field_id |
|
|
sput-object vx,field_id |
|
|
sput-boolean vx,field_id |
|
|
sput-byte vx,field_id |
|
|
sput-char vx,field_id |
|
|
sput-short vx,field_id |
|
|
|
|
|
invoke-virtual { parameters }, methodtocall |
|
|
invoke-super {parameter},methodtocall |
|
|
invoke-direct { parameters }, methodtocall |
|
|
invoke-static {parameters}, methodtocall |
|
|
invoke-interface {parameters},methodtocall |
|
|
invoke-virtual/range {vx..vy},methodtocall |
|
|
invoke-super/range |
|
|
invoke-direct/range {vx..vy},methodtocall |
|
|
invoke-static/range {vx..vy},methodtocall |
|
|
invoke-interface-range |
|
|
neg-int vx,vy | vx=-vy. |
|
not-int vx,vy |
|
|
neg-long vx,vy | vx,vx+1=-(vy,vy+1) |
|
not-long vx,vy |
|
|
neg-float vx,vy |
|
|
neg-double vx,vy |
|
|
int-to-long vx, vy | 强转vy到 vx,vx+1 |
|
int-to-float vx, vy |
|
|
int-to-double vx, vy |
|
|
long-to-int vx,vy | 强转 vy,vy+1到vx |
|
long-to-float vx, vy |
|
|
long-to-double vx, vy |
|
|
float-to-int vx, vy |
|
|
float-to-long vx,vy |
|
|
float-to-double vx, vy |
|
|
double-to-int vx, vy |
|
|
double-to-long vx, vy |
|
|
double-to-float vx, vy |
|
|
int-to-byte vx,vy |
|
|
int-to-char vx,vy |
|
|
int-to-short vx,vy |
|
|
add-int vx,vy,vz | Vz加上vy并赋值给vx (int) |
|
sub-int vx,vy,vz | 减 |
|
mul-int vx, vy, vz | 乘 |
|
div-int vx,vy,vz rem-int vx,vy,vz | 除 求余 |
|
and-int vx, vy, vz | 与 |
|
or-int vx, vy, vz | 或 |
|
xor-int vx, vy, vz | 异或 |
|
shl-int vx, v y, vz | 将vy左移vz位,并将结果存到vx |
|
shr-int vx, vy, vz | 将vy右移vz位,并将结果存到vx |
|
ushr-int vx, vy, vz | 无符号右移 |
|
add-long vx, vy, vz | Vz加上vy并赋值给vx (long) |
|
sub-long vx,vy,vz |
|
|
mul-long vx,vy,vz |
|
|
div-long vx, vy, vz |
|
|
rem-long vx,vy,vz |
|
|
and-long vx, vy, vz |
|
|
or-long vx, vy, vz |
|
|
xor-long vx, vy, vz |
|
|
shl-long vx, vy, vz |
|
|
shr-long vx,vy,vz |
|
|
ushr-long vx, vy, vz |
|
|
add-float vx,vy,vz | Vz加上vy并赋值给vx (float) |
|
sub-float vx,vy,vz |
|
|
mul-float vx, vy, vz |
|
|
div- float vx, vy, vz |
|
|
rem-float vx,vy,vz |
|
|
add-double vx,vy,vz | Vz加上vy并赋值给vx (double) |
|
sub-double vx,vy,vz |
|
|
mul-double vx, vy, vz |
|
|
div- double vx, vy, vz |
|
|
rem-double vx,vy,vz |
|
|
sub-int/2addr vx,vy | Vx加vy并将值赋给vx |
|
add-int/2addr vx,vy |
|
|
mul-int/2addr vx,vy |
|
|
div-int/2addr vx,vy |
|
|
rem-int/2addr vx,vy |
|
|
and-int/2addr vx, vy |
|
|
or-int/2addr vx, vy |
|
|
xor-int/2addr vx, vy |
|
|
shl-int/2addr vx, vy |
|
|
shr-int/2addr vx, vy |
|
|
ushr-int/2addr vx, vy |
|
|
add-long/2addr vx,vy | Vx加vy并将值赋给vx |
|
sub-long/2addr vx,vy |
|
|
mul-long/2addr vx,vy |
|
|
div-long/2addr vx,vy |
|
|
rem-long/2addr vx,vy |
|
|
and-long/2addr vx, vy |
|
|
or-long/2addr vx, vy |
|
|
xor-long/2addr vx, vy |
|
|
shl-long/2addr vx, vy |
|
|
shr-long/2addr vx, vy |
|
|
ushr-long/2addr vx, vy |
|
|
add-long/2addr vx,vy |
|
|
sub-long/2addr vx,vy |
|
|
mul-long/2addr vx,vy |
|
|
div-long/2addr vx,vy |
|
|
rem-long/2addr vx,vy |
|
|
add-float/2addr vx,vy | Vx加vy并将值赋给vx |
|
sub- float /2addr vx,vy |
|
|
mul- float /2addr vx,vy |
|
|
div- float /2addr vx,vy |
|
|
rem- float /2addr vx,vy |
|
|
add-double/2addr vx,vy | Vx加vy并将值赋给vx |
|
sub- double /2addr vx,vy |
|
|
mul- double /2addr vx,vy |
|
|
div- double /2addr vx,vy |
|
|
rem- double /2addr vx,vy |
|
|
add-int/lit16 vx,vy,lit16 | 将一个数字与vy相加并赋值给vx | add-int/lit16 v1, v0, ox234 |
sub-int/lit16 vx,vy,lit16 |
|
|
mul-int/lit16 vx,vy,lit16 |
|
|
div-int/lit16 vx,vy,lit16 |
|
|
rem-int/lit16 vx,vy,lit16 |
|
|
and-int/lit16 vx,vy,lit16 |
|
|
or-int/lit16 vx,vy,lit16 |
|
|
xor-int/lit16 vx,vy,lit16 |
|
|
add-int/lit8 vx,vy,lit8 |
|
|
sub-int/lit8 vx,vy,lit8 |
|
|
mul-int/lit8 vx,vy,lit8 |
|
|
div-int/lit8 vx,vy,lit8 |
|
|
rem-int/lit8 vx,vy,lit8 |
|
|
and-int/lit8 vx,vy,lit8 |
|
|
or-int/lit8 vx, vy, lit8 |
|
|
xor-int/lit8 vx, vy, lit8 |
|
|
shl-int/lit8 vx, vy, lit8 |
|
|
shr-int/lit8 vx, vy, lit8 |
|
|
ushr-int/lit8 vx, vy, lit8 | 将vy右移(无符号)指定位数赋值给vx |
|
|
|
|
execute-inline {parameters},inline ID | 这个是一个不安全的结构 | execute-inline {v1, v0}, inline #0003 |
invoke-direct-empty |
| invoke-direct-empty {v0}, Ljava/lang/Object;.<init>:()V |
iget-quick vx,vy,offset |
| iget-quick v1, v2, [obj+0010] |
iget-wide-quick vx,vy,offset |
| iget-wide-quick v4, v6, [obj+0130] |
iget-object-quick vx,vy,offset |
| iget-object-quick v1, v3, [obj+000c] |
iput-quick vx,vy,offset |
| iput-quick v1, v2, [obj+0010] |
iput-wide-quick vx,vy,offset |
| iput-wide-quick v2, v5, [obj+0170] |
iput-object-quick vx,vy,offset |
| iput-object-quick v1, v0, [obj+004c] |
invoke-virtual-quick {parameters},vtable offset |
| invoke-virtual-quick {v15, v12}, vtable #00b8 |
invoke-virtual-quick/range {parameter range},vtable offset |
| invoke-super-quick {v2, v3, v4, v5}, vtable #0081 |
invoke-super-quick {parameters},vtable offset |
| invoke-super-quick {v2, v3, v4, v5}, vtable #0081 |
invoke-super-quick/range {register range},vtable offset |
| invoke-super-quick/range {v0..v5}, vtable #001b |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|