从类的角度去理解smali的文件组织结构。
内部类:
public classMainActivity extends Activity {
public class firstinner
{
public class secondinner
{
public class thirdinner
{
}
}
}
}
对于形如此类的内部类声明格式。
文件的产生方式为:
即: [外部类]$内部类.smali 的形式,并依此迭代。
对于匿名的内部类,将以[外部类]$NUM.smali。的形式迭代,NUM代表从1开始的数字。
打开文件:MainActivity$firstinner$secondinner.smali
1、其中开头的注解域为
# annotations
#表明MainActivity$firstinner$secondinner这个类的作用范围,EnclosingClass 表明作用范围//是一个类,value表明的就是作用于MainActivity$firstinner这个类。还有EnclosingMethod,//表明类作用的范围是一个方法。比如声明在一个方法里面的监听类等。
.annotationsystem Ldalvik/annotation/EnclosingClass; value = Lcom/example/smali/MainActivity$firstinner; .end annotation
#accessFlags
enum {
kDexVisibilityBuild = 0x00, /*annotation visibility */
kDexVisibilityRuntime = 0x01,
kDexVisibilitySystem = 0x02,
};
.annotationsystem Ldalvik/annotation/InnerClass; #表明本身是一个内部类 accessFlags = 0x1 name = "secondinner" .end annotation
.annotationsystem Ldalvik/annotation/MemberClasses; #列出了内部类的列表 value = { Lcom/example/smali/MainActivity$firstinner$secondinner$thirdinner; } .end annotation
2、实例域
# instance fields .field final syntheticthis$1:Lcom/example/smali/MainActivity$firstinner;
Synthetic代表它是由编译器合成的,虚构的。
this$1 内部类存储的外部类的一个引用。即Lcom/example/smali/MainActivity$firstinner;的引用。
3、对于一个有内容的内部类SNChecker。有如下构造函数
# direct methods .method publicconstructor <init> (Lcom/droider/crackme0502/MainActivity;Ljava/lang/String;)V .locals0 #在这个函数中最少要用到的本地寄存器的个数 .parameter #p1 -> 代表Lcom/droider/crackme0502/MainActivity的引用 .parameter "sn" #p2 -> Ljava/lang/String字符串sn .prologue #具体代码的开始 .line 83 iput-object p1, p0,Lcom/droider/crackme0502/MainActivity$SNChecker ;->this$0 :Lcom/droider/crackme0502/MainActivity; invoke-direct {p0},Ljava/lang/Object;-><init>()V #代表调用Ljava/lang/Object;类型的直接方法。参数是p0。 .line 84 iput-object p2, p0,Lcom/droider/crackme0502/MainActivity$SNChecker;->sn:Ljava/lang/String; .line 85 return-void #返回空 .end method
#有两种寄存器命名方式,V命名 和 P命名。 在一个函数中,V命名代表函数内声明的局部变量;P命名代表函数中引入的参数变量。
#以.method 和.end method 包围一个方法。 “publicconstructor <init>”是方法的修饰。
括号里面的是参数(Lcom/droider/crackme0502/MainActivity; Ljava/lang/String; )
最后的V代表返回的类型。返回类型为空void
#.locals 在这个函数中最少要用到的本地寄存器的个数。如果是 .registers4 这种形式代表使用v0、v1、v2寄存器与一个参数寄存器
#. parameter 代表函数引入的参数声明,有几个参数,就有几个parameter 。
# iput-object p1, p0,L… 代表,将p1的值放入p0中。P1的值来源于L…中声明的引用。
# Lcom/droider/crackme0502/MainActivity$SNChecker;->sn : Ljava/lang/String;
冒号之前的部分“Lcom/droider/crackme0502/MainActivity$SNChecker;”代表后面的变量属于哪个类的成员。即sn属于此内容中的成员。 冒号后面的部分“Ljava/lang/String;”代表此程序的类型。这里代表String字符串类型。
Smali数据类型:
B---byte
C---char
D---double
F---float
I---int
J---long
S---short
V---void
Z---boolean
[XXX---array
Lxxx/yyy---object
关于函数的几种调用方式,有一个很好的参考总结。五种调用方式。
invoke-direct,invoke-virtual,invoke-static、invoke-super以及invoke-interface
最常用的是invoke-direct,invoke-virtual。
invoke-direct代表使用private方法。
invoke-virtual代表public或者 protected。
http://blog.csdn.net/lpohvbe/article/details/7981386