轉載請聲明出處 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代表的是,調用父類的無參構造方法,進行初始化。
好了今天內容到此結束,其他知識點將會在下一篇繼續進行