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或
· 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 |
|
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 |
|
if-ge vx, vy,target |
Vx>=vy |
|
if-gt vx,vy,target |
Vx>vy |
|
if-le vx,vy,target |
Vx |
|
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;. |
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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|