Smali从入门到精通(二)之方法定义

转载请声明出处 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代表的是,调用父类的无参构造方法,进行初始化。

好了今天内容到此结束,其他知识点将会在下一篇继续进行

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章