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代表的是,調用父類的無參構造方法,進行初始化。

好了今天內容到此結束,其他知識點將會在下一篇繼續進行

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