转载请声明出处 https://blog.csdn.net/YoYo_Newbie/article/details/90745902
根据上一篇内容,我们已经初步了解了Smali以及文件的声明。接下来我们将认识类的方法的定义,请看下面这个类csdn.yoyo_newbie.smalianalyzesample.Test1
package csdn.yoyo_newbie.smalianalyzesample;
import android.util.Log;
public class Test1 {
private void logger(){
Log.e("test", "hello smali");
}
}
反编译后,生成csdn\yoyo_newbie\smalianalyzesample\Test1.smali
.class public Lcsdn/yoyo_newbie/smalianalyzesample/Test1;
.super Ljava/lang/Object;
.source "Test1.java"
# direct methods
.method public constructor <init>()V
.locals 0
.prologue
.line 5
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
.method private logger()V
.locals 2
.prologue
.line 8
const-string/jumbo v0, "test"
const-string/jumbo v1, "hello smali"
invoke-static {v0, v1}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I
.line 9
return-void
.end method
来,先看着这一个方法,后面将一步步分析
private void logger(){
Log.e("test", "hello smali");
}
生成对于的smali代码为
.method private logger()V
.locals 2
.prologue
.line 8
const-string/jumbo v0, "test"
const-string/jumbo v1, "hello smali"
invoke-static {v0, v1}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I
.line 9
return-void
.end method
如下, 下面这2个语法代表包裹的代码是一个方法,.method是方法开始,.end method代表结束.(如果想要加深记忆,你可以想象汇编中的方法的堆栈平衡)
.method
.end method
在这一行中
.method private logger()V
.method方法后面紧接的是方法的作用域的修饰符,代表这个方法是private的,然后private后面紧接的是方法的名称,后面紧接的是方法的参数声明,而()V则是代表无参。对于参数类型,有如下标准的转换
Java | Smali |
---|---|
byte | B |
char | C |
double | D |
float | F |
int | I |
short | S |
void | V |
long | J |
boolean | Z |
class | L |
无参 | V |
注意!在表格中,long对应不是L,不要搞混乱了,它对应的是J,而class对于的才是L,如java.lang.String对应smali为Ljava/lang/String
如果要表示数组参数,在前面加一个’[’,
如
Java | Smali |
---|---|
byte数组 | [B |
int数组 | [I |
接下来要解析
.locals 2
locals代表时候多少个局部类型数据,也就是说它的意思是,这个方法是有2个局部类型数据。这时候你就觉得有点奇怪,哪有2个局部类型数据。其实是这样的。
private void logger(){
Log.e("test", "hello smali");
}
这个方法,编译器编译后会变成这样
private void logger(){
final String v0 = "test";
final String v1 = "hello smali";
Log.e(v0, v1);
}
所以,真的是2个局部类型数据
接下来,是
.prologue
prologue代表方法名以及参数定义声明完毕,接下来的内容是方法将要执行的内容部分。
然后,接下来是
.line 8
line的值代表当前代码是在java文件中第几行
以下意思是,等价于 final String v0 = “test”;
const-string/jumbo v0, “test”
等价于 final String v1 = “hello smali”;
const-string/jumbo v1, “hello smali”
其中,const-string/jumbo 声明的引用是获取字符串常量池的数据。
接下来是
invoke-static {v0, v1}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I
invoke-static代表调用静态方法调用。后面紧接的是{传参…},然后后面是代表是这个静态方法是谁的以及方法名,参数格式和返回类型。
也就是 invoke-static+{参数}+L类;->方法名(参数类型…)返回类型
最后是,这代表这个方法返回值类型是void类型
return-void
好了,看完这里,你再去看这部分,没错,你已经猜出来了。这是类的构造方法,和其他的方法区别不大,只是用了constructor来声明和初始标识而已
.method public constructor <init>()V
.locals 0
.prologue
.line 5
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
其中,invoke-direct {p0}, Ljava/lang/Object;->()V代表的是,调用父类的无参构造方法,进行初始化。
好了今天内容到此结束,其他知识点将会在下一篇继续进行