1. 程式人生 > >(轉)smali語言程式流程控制語法

(轉)smali語言程式流程控制語法

https://blog.csdn.net/Ceryool/article/details/51314394

選擇結構(if-else)

smali條件跳轉分支語法

if-<條件> v0 v1,:cond_** // 如果v0<條件>v1成立,則跳轉到:cond_**處的程式碼。
if-eq vA, vB, :cond_1f   //如果vA等於vB則程式跳轉到:cond_1f處的程式碼執,行。

條件判斷關鍵字如下

java程式碼

int a = 2;
int b = 3;
int c = 4;
private void ifelseMethod() {
    if (b > c) {
       Log.d(TAG, "b>c");
    } else if (b > a) {
        Log.d(TAG, "b>a");
    } else {
        Log.d(TAG, "b<a, b<c");
    }
}  

smali程式碼

.method private ifelseMethod()V
    .registers 3

    .prologue
    .line 65
    iget v0, p0, Lcom/example/user/smalitest/MainActivity;->b:I#v0--b

    iget v1, p0, Lcom/example/user/smalitest/MainActivity;->c:I#v1--c

    if-le v0, v1, :cond_e #如果v0小於等於v1(java程式碼中if(b>c)不成立)則跳轉到:cond_e處執行程式碼(第24行),否則接著往下執行

    .line 66
    iget-object v0, p0, Lcom/example/user/smalitest/MainActivity;->TAG:Ljava/lang/String;#這裡是(b>c)情況下執行的程式碼

    const-string v1, "b>c"

    invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

    .line 73
    :goto_d#標記:goto_d,   在其他地方的程式碼出現goto :goto_d,程式會跳轉到這裡執行
    return-void#return void 跳出方法,後邊其他的程式碼都不會執行

    .line 67
    :cond_e#標記cond_e, 如果在前邊(第10行)"b<=c"的情況下,程式會跳轉到cond_e 即這裡接著往下執行
    iget v0, p0, Lcom/example/user/smalitest/MainActivity;->b:I#v0--b

    iget v1, p0, Lcom/example/user/smalitest/MainActivity;->a:I#v0--a

    if-le v0, v1, :cond_1c#如果v0小於等於v1(java中 b>a)跳轉到:cond_1c處(第41行)執行,否則接著往下執行

    .line 68
    iget-object v0, p0, Lcom/example/user/smalitest/MainActivity;->TAG:Ljava/lang/String;

    const-string v1, "b>a"

    invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

    goto :goto_d #跳轉到標記為 :goto_d的地方(第20行)執行,

    .line 70
    :cond_1c
    iget-object v0, p0, Lcom/example/user/smalitest/MainActivity;->TAG:Ljava/lang/String;

    const-string v1, "b<a, b<c"

    invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

    goto :goto_d
.end method

迴圈結構

在smali中迴圈的實現就是通過無條件跳轉語句goto 加條件語句if-<條件>相結合實現。

#例如for迴圈,while迴圈
:goto_1
if_<條件> v0 v1,  :cond_2 #如果滿足條件的時候就跳轉到cond_2v處。
#迴圈內容
goto :goto_1

:cond_2 
#迴圈結束的程式碼

do-while迴圈

:cond_1 #迴圈開始
#迴圈體
if_<條件> v0 v1, :cond_1 #如果滿足v0 v1 滿足條件 跳轉到:cond_1繼續迴圈
#迴圈結束程式碼

for迴圈例子

java程式碼

private void forMethod() {
    for (int i = 0; i < 3; i++) {
        Log.d("TAG", "Button1 Log:" + i);
    }
}

smali程式碼

.method private forMethod()v
     .registers 5

    .prologue
    .line 93
    const/4 v0, 0x0

    .local v0, "i":I
    :goto_1     //迴圈開始
    const/4 v1, 0x3

    if-ge v0, v1, :cond_1f   //判斷條件 滿足v0>=v1 程式跳轉到 :cond_1f(跳出迴圈) v0就是i的值,v1為3(在java中 當不滿足i<3時,跳出迴圈,即當i>=3時)

    .line 94
    const-string v1, "TAG"

    new-instance v2, Ljava/lang/StringBuilder;

    invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()V

    const-string v3, "Button1 Log:"

    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v2

    invoke-static {v1, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

    .line 93
    add-int/lit8 v0, v0, 0x1

    goto :goto_1  //跳轉到 :goto_1 繼續迴圈

    .line 96
    :cond_1f  //跳出迴圈後執行
    return-void
.end method

while迴圈例子

java程式碼

    private void whileMethod() {
        int k = 0;
        while (k < 5) {
            k++;
            Log.d("TAG", "Button3 Log:" + k);
        }
    }

smali程式碼

.method private whileMethod()V
    .registers 5

    .prologue
    .line 76
    const/4 v0, 0x0

    .line 77
    .local v0, "k":I
    :goto_1   //迴圈開始
    const/4 v1, 0x5  //v1 值為5

    if-ge v0, v1, :cond_1f 判斷條件 如果v0>=v1 跳轉到:cond_1f處,否則繼續迴圈(java中當k<5時,繼續迴圈)

    .line 78
    add-int/lit8 v0, v0, 0x1  //java中k++

    .line 79
    const-string v1, "TAG"

    new-instance v2, Ljava/lang/StringBuilder;

    invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()V

    const-string v3, "Button3 Log:"

    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v2

    invoke-static {v1, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

    goto :goto_1 //跳轉到goto_1 繼續迴圈

    .line 81
    :cond_1f //跳出迴圈後 從這裡繼續執行
    return-void
.end method

do-while迴圈例子

java程式碼

    private void doWhileMethod() {
        int j = 0;
        do {
            j++;
            Log.d("TAG", "Button2 Log:" + j);
        } while (j < 5);

    }

smali程式碼

.method private doWhileMethod()V
    .registers 5

    .prologue
    .line 84
    const/4 v0, 0x0

    .line 86
    .local v0, "j":I
    :cond_1  //標記:cond_1  從這裡開始迴圈
    add-int/lit8 v0, v0, 0x1  //java中  j++;

    .line 87
    const-string v1, "TAG"

    new-instance v2, Ljava/lang/StringBuilder;

    invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()V

    const-string v3, "Button2 Log:"

    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v2

    invoke-static {v1, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

    .line 88
    const/4 v1, 0x5  //v1---5

    if-lt v0, v1, :cond_1   //如果v0<v1(java中 j<5),就跳轉到:cond_1處繼續迴圈

    .line 90
    return-void
.end method

分支結構

分支結構在smali中有兩種, 第一中,case的值是連續遞增的,關鍵字packed-switch ,如下所示:

packed-switch p1, :pswitch_data_0  #p1為傳遞進來的要匹配case值的引數
:goto_0 
#退出分支結構程式碼
:pswitch_0
#case0時的程式程式碼
goto :goto_0    #跳轉到分支結構退出程式碼
:pswitch_1
#程式程式碼
goto :goto_0
:pswitch_2
#程式程式碼
goto :goto_0
:pswitch_data_0 
 .packed-switch 0x0  #case值開始的地方,一次遞增
     :pswitch_0      #case 0:
     :pswitch_1      #case 1:
     :pswitch_2      #case 2:
.end packed-switch 

第二種 ,case值可以為任意值,關鍵字sparse-switch,如下所示

sparse-switch p1, :switch_data_0    #p1 傳進來的引數,跳轉到

:goto_0   #case 出口
#程式碼
:pswitch_0   #case 5 跳轉到這裡
#case值等於5時的程式程式碼
goto :goto_0    #跳轉到分支結構退出程式碼
:pswitch_1
#程式程式碼
goto :goto_0
:pswitch_2
#程式程式碼
goto :goto_0
:pswitch_data_0 
 .sparse-switch   #case值開始的地方,一次遞增
     0x5 -> :pswitch_0      #case 5:
     0xf -> :pswitch_1      #case 15:
     0x23 -> :pswitch_2      #case 35:
.end packed-switch 

java程式碼

    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_1:
                forMethod();
                break;
            case R.id.btn_2:
                doWhileMethod();
                break;
            case R.id.btn_3:
                whileMethod();
                break;
            case R.id.btn_4:
                ifelseMethod();
                break;
        }
    }

smali程式碼

.method public onClick(Landroid/view/View;)V
    .registers 3
    .param p1, "view"    # Landroid/view/View;

    .prologue
    .line 47
    invoke-virtual {p1}, Landroid/view/View;->getId()I

    move-result v0

    packed-switch v0, :pswitch_data_18 #switch分支開始除,v0為引數 即Java中view.getId()值。

    .line 62
    :goto_7
    return-void

    .line 49
    :pswitch_8
    invoke-direct {p0}, Lcom/example/user/smalitest/MainActivity;->forMethod()V

    goto :goto_7

    .line 52
    :pswitch_c
    invoke-direct {p0}, Lcom/example/user/smalitest/MainActivity;->doWhileMethod()V

    goto :goto_7

    .line 55
    :pswitch_10
    invoke-direct {p0}, Lcom/example/user/smalitest/MainActivity;->whileMethod()V

    goto :goto_7

    .line 58
    :pswitch_14
    invoke-direct {p0}, Lcom/example/user/smalitest/MainActivity;->ifelseMethod()V

    goto :goto_7

    .line 47
    :pswitch_data_18
    .packed-switch 0x7f0c0050   
        :pswitch_8
        :pswitch_c
        :pswitch_10
        :pswitch_14
    .end packed-switch
.end method