1、Smali中的包信息
- .class <訪問權限> [修飾關鍵字] <類名>
- .super <父類名>
- .source <源文件名>
.class public Lcom/aaa;
.super Lcom/bbb;
.source "ccc.java"
該smali文件是由ccc.java編譯而來的,它是com.aaa這個包下的一個類,繼承自com.bbb這個類
2、Smali中的寄存器知識
- 本地寄存器以v開頭數字結尾,如:v0,v1...
- 參數寄存器以p開頭數字結尾,如:p0,p1...
- p0不一定是函數中的第一個參數,在非static函數中,p0就是“this”的意思,後面的才爲函數參數
3、Smali中的函數
函數的整體架構:
.method <訪問權限> [修飾關鍵字] <方法原型> #方法聲明
<.locals> #局部變量個數
[.parameter] #參數
[.prologue] #代碼開始處
[.line] #源代碼行號
<代碼體>
.end method #方法結束
4、Smali中的數據類型
- v void只能用於返回值類型
- Z boolean類型
- B byte類型
- S shot類型
- C char類型
- I int類型
- J long類型
- F float類型
- D double類型
- 數組類型: [
- [後面跟着基本數據類型
- 如:float [] ===> [F
- char [][] ===> [[C
- 對象類型:L<包名>/<類名>;
- 分號表示對象結束
- String對象 ===> Ljava/lang/String;
- 內部類前面加 “ $ ” 符號:L<包名>/<類名>$<內部類名>;
5、Smali中的成員變量
- 格式:.field [訪問權限] [修飾關鍵字] <變量名>:<數據類型>
- 成員變量的獲取指令:iget、sget、iget-boolean、sget-boolean、iget-object、sget-object等
- 成員變量的操作指令:iput、sput、iput-boolean、sput-boolean、iput-object、sput-object等
- 除了帶有-object和-boolean之外的指令操作的是基本數據類型
- get指令的使用:
- 如:sget-object v0, Lcom/aaa;->ID:Ljava/lang/String;
- 表示的是獲取String類型的ID變量的值,並將其存放到v0寄存器中
- 前面爲該變量所屬類的類型,在冒號後面表示變量的數據類型,“->”表示所屬關係
- 表示的是獲取String類型的ID變量的值,並將其存放到v0寄存器中
- iget-object v0,p0,Lcom/aaa;->view:Lcom/aaa/view;
- p0爲該變量所在類的實例,即“this”
- 獲取數組的話,用aget-object
- 如:sget-object v0, Lcom/aaa;->ID:Ljava/lang/String;
- put指令的使用:
- const/4 v1, 0x0
- sput-object v3, Lcom/aaa;->timer:Lcom/aaa/timer; ===> this.timer=null;
- 因爲給object對象賦值,所以爲null
- .local v0, args:Landroid/os/Message;
- const/4 v1, 0x12
- iput v1, v0, Landroid/os/Message;->what:I ===> args.what=18;
- 實例化對象Message爲args並存放在寄存器v0中,給v1賦值爲0x12,然後使用iput將v1的值賦給args對象的what屬性
6、Smali其他基本語法:
- .invoke-super #調用父類方法
- const/high16 v0, 0xadf1 #將0xadf1存放到寄存器v0中
- invoke-direct #調用函數
- return-void #函數返回void
- new-instance #創建實例
- iput-object #給對象賦值
- iget-object #調用對象
- invoke-static #調用靜態函數
7、Smali中的條件分支
- if-eq v1, v2:cond_* ===> 如果v1=v2則跳轉到:cond_*
- if-ne v1, v2:cond_* ===> 如果v1≠v2則跳轉到:cond_*
- if-lt v1, v2:cond_* ===> 如果v1<v2則跳轉到:cond_*
- if-le v1, v2:cond_* ===> 如果v1<=v2則跳轉到:cond_*
- if-ge v1, v2:cond_* ===> 如果v1>=v2則跳轉到:cond_*
- if-gt v1, v2:cond_* ===> 如果v1>v2則跳轉到:cond_*
- if-eqz v1:cond_* ===> 如果v1=0則跳轉到:cond_*
- if-nez v1:cond_* ===> 如果v1≠0則跳轉到:cond_*
- if-ltz v1:cond_* ===> 如果v1<0則跳轉到:cond_*
- if-lez v1:cond_* ===> 如果v1<=0則跳轉到:cond_*
- if-gtz v1:cond_* ===> 如果v1>0則跳轉到:cond_*
- if-gez v1:cond_* ===> 如果v1>=0則跳轉到:cond_*
8、Smali中的函數調用
- 函數分爲兩種:direct和virtual
- direct method表示private
- virtual method表示public、protected
- 在函數調用時有:invoke-direct、invoke-virtual、invoke-static、invoke-super等
- 當參數多於4個的時候使用:invoke-xxx/range
- invoke-static:用於調用靜態函數
- invoke-static {}, Lcom/aaa;->Check()Z
- {}:裏面的東西表示傳入函數的實例+參數列表,由於該static函數不需要任何參數所以裏面爲空
- const-string v0, "NIUBI"
- invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
- 這是調用static void System.loadLibrary(String)方法,傳入的參數爲“NIUBI”
- invoke-static {}, Lcom/aaa;->Check()Z
- invoke-super:調用父類方法,一般用於調用onCreate、onDestroy等方法
- invoke-direct:調用private函數
- invoke-direct {p0}, Landroid/app/TabActivity;-><init>()V
- 這裏的<init>就是定義在TabActivity中的private函數
- invoke-direct {p0}, Landroid/app/TabActivity;-><init>()V
- invoke-virtual:調用的是public、protected函數
- sget-object v0, Lcom/aaa;->bbb:Lcom/ccc;
- invoke-virtual {v0, v1}, Lcom/ccc;->Message(Ljava/lang/Object;)V
- v0是Lcom/ccc
- v1是傳給Message方法的Ljava/lang/Object;參數
- public void ccc.Message(Object)
- invoke-xxxx/range:當方法的參數多於4個的時候使用
- 在調用函數的時候通常會有返回結果,如果返回值非void,則需要使用
- move-result (返回基本數據類型)和move-result-object (返回對象)
- const-string v0, "Eric"
- invoke-static {v0}, Lcmb/pbi;->t(Ljava/lang/String;)Ljava/lang/String;
- move-result-object v2
- v2就保存了t方法的返回值String類型的