編輯:關於Android編程
Dalvik字節碼只有兩種格式:基本類型和引用類型。對象和數組屬於引用類型
Ljava/lang/String; 相當於java.lang.String
[I 相當於一維int數組,int[]
[[I 相當於int[][]
它使用方法名,參數類型和返回值來描述一個方法
package/name/ObjectName;->methodName(III)Z
package/name/ObjectName:一個類
methodName:方法名
III:參數類型
Z:返回值
(III)Z:方法簽名
BakSmali生成的方法代碼以.method指令開始,以.end method指令結束,根據方法的類型不同,可以會在方法前加#表示方法類型
# vitual methods:虛方法,如:
# virtual methods .method public get(Ljava/lang/String;)Lcn/woblog/markdowndiary/domain/Note; .locals 2 .param p1, "noteId" # Ljava/lang/String; .prologue .line 50 iget-object v0, p0, Lcn/woblog/markdowndiary/repository/LocalNoteRepository;->orm:Lcom/litesuits/orm/LiteOrm; const-class v1, Lcn/woblog/markdowndiary/domain/Note; invoke-virtual {v0, p1, v1}, Lcom/litesuits/orm/LiteOrm;->queryById(Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object; move-result-object v0 check-cast v0, Lcn/woblog/markdowndiary/domain/Note; return-object v0 .end method
# direct methods:直接方法,如:
# direct methods .method public constructor(Landroid/content/Context;)V .locals 2 .param p1, "context" # Landroid/content/Context; .prologue .line 22 invoke-direct {p0}, Ljava/lang/Object;-> ()V .line 23 iput-object p1, p0, Lcn/woblog/markdowndiary/repository/LocalNoteRepository;->context:Landroid/content/Context; .line 24 const-string v0, "note.db" invoke-static {p1, v0}, Lcom/litesuits/orm/LiteOrm;->newSingleInstance(Landroid/content/Context;Ljava/lang/String;)Lcom/litesuits/orm/LiteOrm; move-result-object v0 iput-object v0, p0, Lcn/woblog/markdowndiary/repository/LocalNoteRepository;->orm:Lcom/litesuits/orm/LiteOrm; .line 25 iget-object v0, p0, Lcn/woblog/markdowndiary/repository/LocalNoteRepository;->orm:Lcom/litesuits/orm/LiteOrm; const/4 v1, 0x1 invoke-virtual {v0, v1}, Lcom/litesuits/orm/LiteOrm;->setDebugged(Z)V .line 26 return-void .end method
有些方法沒有這樣的注釋
.method public save(Lcn/woblog/markdowndiary/domain/Note;)V .locals 1 .param p1, "note" # Lcn/woblog/markdowndiary/domain/Note; .prologue .line 37 iget-object v0, p0, Lcn/woblog/markdowndiary/repository/LocalNoteRepository;->orm:Lcom/litesuits/orm/LiteOrm; invoke-virtual {v0, p1}, Lcom/litesuits/orm/LiteOrm;->save(Ljava/lang/Object;)J .line 38 return-void .end method
靜態方法:
.method public static formatTime(J)Ljava/lang/String; .locals 4 .param p0, "date" # J .prologue .line 11 new-instance v0, Ljava/text/SimpleDateFormat; const-string v1, "yyyy\u5e74MM\u6708dd\u65e5 EEEE" sget-object v2, Ljava/util/Locale;->CHINESE:Ljava/util/Locale; invoke-direct {v0, v1, v2}, Ljava/text/SimpleDateFormat;->(Ljava/lang/String;Ljava/util/Locale;)V .line 13 .local v0, "simpleDateFormat":Ljava/text/SimpleDateFormat; invoke-static {p0, p1}, Ljava/lang/Long;->valueOf(J)Ljava/lang/Long; move-result-object v1 invoke-virtual {v0, v1}, Ljava/text/SimpleDateFormat;->format(Ljava/lang/Object;)Ljava/lang/String; move-result-object v1 return-object v1 .end method
與方法表示很相似,只是字段沒有方法簽名和返回值,取而代之的是字段類型
Lpackage/name/ObjectName;->FiedlName:Ljava/lang/String;
其中字段名與字段類型用冒號“:”分割
# static fields .field private static instance:Lcn/woblog/markdowndiary/repository/LocalNoteRepository; # instance fields .field private final context:Landroid/content/Context;
其中:
# static fields:靜態字段
# instance fields:實例字段
他在調用格式上模仿了C語言的調用約定,官方地址,指令語法與助詞有如下特點:
采用采用從目標(destination)到源(source)的方法 根據字節碼的大小與類型不同,一些字節碼添加了名稱後綴已消除歧義如:
move-wide/from16 vAA, vBBBB
move-wide/from16 v18, v0
move:基礎字節碼(base opcode),標示是基本操作
wide:標示指令操作的數據寬度為64位寬度
from16:字節碼後綴(opcode suffix),標示源(vBBBB)為一個16的寄存器引用變量
vAA:目的寄存器,v0~v255
vBBBB:源寄存器,v0~v65535
空操作,被用來做對齊代碼
用來定義程序中用到的常量,字符串,類等數據
const/4 vA, #+B :將數組擴展為32位後賦給寄存器vA
const/16 vAA, #+BBBB
const vAA, #+BBBBBBBB:將數組賦值給寄存器vAA
const-wide/16 vAA, #+BBBBB :將數值擴展為64位後賦給寄存器vAA
const-string vAA, string@BBBB:將字符串索引構造一個字符串並賦給vAA
const-class vAA, type@BBBB:通過類型索引獲取一個類的引用並賦給寄存器vAA
private void testConst() { int a = 1; int b = 7; int c = 254; int d = 2345; int d1 = 65538; long e = 12435465657677L; float f = 123235409234.09097945F; double g = 111343333454999999999.912384375; }
//-8到7用4,大於255小於等於65535用16 const/4 v0, 0x1 .line 25 .local v0, "a":I const/4 v1, 0x7 .line 26 .local v1, "b":I const/16 v2, 0xfe .line 27 .local v2, "c":I const/16 v3, 0x929 .line 28 .local v3, "d":I const v4, 0x10002 //65538,大於65535用const v4 //long用const-wide .line 30 .local v4, "d1":I const-wide v6, 0xb4f5b835d4dL .line 31 .local v6, "e":J const v5, 0x51e58b39 .line 32 .local v5, "f":F const-wide v8, 0x441824cbef6b9491L # 1.11343333455E20
move destination, source
根據字節碼大小和類型不同,後面回天津不同的後綴
move vA, vB:vB寄存器值賦值給vA寄存器,都為4位
move-object vA,vB
move-result vAA:將上一個invoke類型的指令操作的單字非對象結果負責vAA寄存器
move-result-object vAA:將上一個invoke類型指令操作的對象賦值給vAA
move-exception vAA:保存一個運行時發生的異常vAA寄存器,必須是異常發生時的異常處理的第一條指令
private void testMove() { int a = 100; long b = 100000000000000000L; int c = a; long d = b; Log.d(TAG,c+""); Log.d(TAG,d+""); int e = getIntResult(); Log.d(TAG,e+""); try { int f = e/c; } catch (ArithmeticException e1) { e1.printStackTrace(); }catch (Exception e1) { e1.printStackTrace(); }finally { } }
//move-result-object invoke-direct {v7}, Ljava/lang/StringBuilder;->()V invoke-virtual {v7, v1}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder; move-result-object v7 const-string v8, "" invoke-virtual {v7, v8}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v7 //move-result invoke-direct {p0}, Lcom/woblog/testsmali/MainActivity;->getIntResult()I move-result v6 //move exception .line 35 :try_start_0 div-int v8, v6, v1 :try_end_0 .catch Ljava/lang/ArithmeticException; {:try_start_0 .. :try_end_0} :catch_0 .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_1 .catchall {:try_start_0 .. :try_end_0} :catchall_0 .line 43 :goto_0 return-void .line 36 :catch_0 move-exception v7 .line 37 .local v7, "e1":Ljava/lang/ArithmeticException; :try_start_1 invoke-virtual {v7}, Ljava/lang/ArithmeticException;->printStackTrace()V :try_end_1 .catchall {:try_start_1 .. :try_end_1} :catchall_0 goto :goto_0 .line 40 .end local v7 # "e1":Ljava/lang/ArithmeticException; :catchall_0 move-exception v8 throw v8 .line 38 :catch_1 move-exception v7 .line 39 .local v7, "e1":Ljava/lang/Exception; :try_start_2 invoke-virtual {v7}, Ljava/lang/Exception;->printStackTrace()V :try_end_2 .catchall {:try_start_2 .. :try_end_2} :catchall_0 goto :goto_0
return-void :返回一個void
return vAA:返回一個32位非對象類型的值,返回寄存器為8位
return-wide vAA:返回一個64位非對象類型的值,返回寄存器為8位
return-object vAA:返回一個對象類型
private String returnObject() { return new String(""); } private float returnFloat() { return 12333334.00234345F; } private double returnDouble() { return 3425465767.9345865; } private long returnLong() { return 12445657999999L; } private int returnInt() { return 1024; } private void returnVoid() { int a = 3; }
.method private returnDouble()D .locals 2 .prologue .line 40 const-wide v0, 0x41e9858eb4fde822L # 3.4254657679345865E9 return-wide v0 .end method .method private returnFloat()F .locals 1 .prologue .line 36 const v0, 0x4b3c3116 # 1.2333334E7f return v0 .end method .method private returnInt()I .locals 1 .prologue .line 48 const/16 v0, 0x400 return v0 .end method .method private returnLong()J .locals 2 .prologue .line 44 const-wide v0, 0xb51bb062a7fL return-wide v0 .end method .method private returnObject()Ljava/lang/String; .locals 2 .prologue .line 32 new-instance v0, Ljava/lang/String; const-string v1, "" invoke-direct {v0, v1}, Ljava/lang/String;->(Ljava/lang/String;)V return-object v0 .end method .method private returnVoid()V .locals 1 .prologue .line 52 const/4 v0, 0x3 .line 53 .local v0, "a":I return-void .end method
鎖指令多用在多線程程序中對同一對象的操作
monitor-enter vAA 為指定的對象獲取鎖
monitor-exit vAA 釋放指定的對象的鎖
private void callSynchronizeClassMethod() { synchronized (MainActivity.class) { Log.d("TAG","synchronized class"); } } private void callSynchronizeMethod() { synchronized (this) { Log.d("TAG","synchronized this"); } } private synchronized void callLockMethod() { Log.d("TAG","synchronized method"); }
.method private declared-synchronized callLockMethod()V .locals 2 .prologue .line 43 monitor-enter p0 :try_start_0 const-string v0, "TAG" const-string v1, "synchronized method" invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I :try_end_0 .catchall {:try_start_0 .. :try_end_0} :catchall_0 .line 44 monitor-exit p0 return-void .line 43 :catchall_0 move-exception v0 monitor-exit p0 throw v0 .end method .method private callSynchronizeClassMethod()V .locals 3 .prologue .line 31 const-class v1, Lcom/woblog/testsmali/MainActivity; monitor-enter v1 .line 32 :try_start_0 const-string v0, "TAG" const-string v2, "synchronized class" invoke-static {v0, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 33 monitor-exit v1 .line 34 return-void .line 33 :catchall_0 move-exception v0 monitor-exit v1 :try_end_0 .catchall {:try_start_0 .. :try_end_0} :catchall_0 throw v0 .end method .method private callSynchronizeMethod()V .locals 2 .prologue .line 37 monitor-enter p0 .line 38 :try_start_0 const-string v0, "TAG" const-string v1, "synchronized this" invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 39 monitor-exit p0 .line 40 return-void .line 39 :catchall_0 move-exception v0 monitor-exit p0 :try_end_0 .catchall {:try_start_0 .. :try_end_0} :catchall_0 throw v0 .end method
包括類型轉換,檢查和創建新實例
check-cast vAA, type@BBBB:將vAA中的對象轉為指定類型,如果失敗會拋出ClassCastException異常,如果類型B是基本類型,對於分基本類型的A來說運行始終是失敗的
instance-of vA, vB, type@CCCC:判斷vB寄存器的對象是否可以轉為指定類型,如果可以vA為1,否則為0
new-instance vAA, type@BBBB:構造一個指定類型的對象,並賦值給vAA寄存器,不能是數組類型
CharSequence cs = new String(); Object o = cs; String s = (String) cs; //實例檢測 if (s instanceof CharSequence) { Log.d("TAG", "ok"); } else { Log.d("TAG","no"); } //創建實例 StringBuilder sb = new StringBuilder(); sb.append("Ok"); String s1 = new String("new string"); String s2 = "string";
new-instance v1, Ljava/lang/String; invoke-direct {v1}, Ljava/lang/String;->()V .line 33 .local v1, "cs":Ljava/lang/CharSequence; move-object v7, v1 .local v7, "o":Ljava/lang/CharSequence; move-object v8, v1 .line 35 check-cast v8, Ljava/lang/String; .line 38 .local v8, "s":Ljava/lang/String; instance-of v12, v8, Ljava/lang/CharSequence; if-eqz v12, :cond_0 .line 39 const-string v12, "TAG" const-string v13, "ok" invoke-static {v12, v13}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 46 :goto_0 new-instance v11, Ljava/lang/StringBuilder; invoke-direct {v11}, Ljava/lang/StringBuilder;-> ()V .line 47 .local v11, "sb":Ljava/lang/StringBuilder; const-string v12, "Ok" invoke-virtual {v11, v12}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; .line 49 new-instance v9, Ljava/lang/String; const-string v12, "new string" invoke-direct {v9, v12}, Ljava/lang/String;-> (Ljava/lang/String;)V .line 50 .local v9, "s1":Ljava/lang/String; const-string v10, "string" .line 51 .local v10, "s2":Ljava/lang/String; return-void .line 41 .end local v9 # "s1":Ljava/lang/String; .end local v10 # "s2":Ljava/lang/String; .end local v11 # "sb":Ljava/lang/StringBuilder; :cond_0 const-string v12, "TAG" const-string v13, "no" invoke-static {v12, v13}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I goto :goto_0
包括獲取數組長度,新建數組,數組賦值,數組元素取值與賦值等
array-length vA, vB:獲取vB寄存器中數組的長度並賦值給vA寄存器
new-array vA, vB, type@CCCC:構造指定類型(type@CCCC)與大小(vB)的數組,並賦值給vA寄存器
filled-new-array {vC,vD,vE,vF,vG}, type@BBBB:構造指定類型(type@BBBB)與大小vA的數組並填充數組內容,除了指定數組的大小還指定了參數個數
filled-new-array/range {vCCCC .. vNNNN}, type@BBBB:與上一條類似,只是參數使用取值范圍,vC是第一個參數寄存器,N=A+C-1
fill-array-data vAA, +BBBBBBBB:vAA為寄存器數組引用,後面跟一個數據表
arrayop vAA, vBB, vCC:對vBB寄存器指定的數組元素進入取值或賦值。vCC指定數組元素索引,vAA寄存器用來存放讀取的或需要設置的值。讀取元素使用age類指令,賦值使用aput類指令,根據數組中存儲的類指令後面會跟不同的後綴:
aget,aget-wide,aget-object,aget-boolean,aget-byte,aget-char,aget-short
aput,aput-wide,aput-object,aput-boolean,aput-byte,aput-char,aput-short
private void testArray() { int[] ints = new int[2]; int[] ints1 = null; int[] ints2 = {1,2,3}; Integer[] integers = new Integer[]{1,2,4}; int[] strings = {1,2,3,4,5,6,5,6,6,6,6,6,6,7,7,8,8,8,8,8,1,1,1,3,3,5,6,54,5,6,56,567,67,6,34,45,45,6,56,57,45,45,5,56,56,7,34,543,543,6,56,56,45,4,54,5,45,56}; //數組長度 int length = ints.length; int length1 = ints2.length; int length2 = strings.length; //獲取數組元素 int string = strings[30]; int string1 = ints2[1]; //賦值 strings[30] = length; ints2[1] = length2; }
.method private testArray()V .locals 15 .prologue const/16 v14, 0x1e const/4 v10, 0x3 const/4 v13, 0x2 const/4 v12, 0x1 .line 27 new-array v1, v13, [I .line 28 .local v1, "ints":[I const/4 v2, 0x0 .line 29 .local v2, "ints1":[I new-array v3, v10, [I fill-array-data v3, :array_0 .line 31 .local v3, "ints2":[I new-array v0, v10, [Ljava/lang/Integer; const/4 v10, 0x0 invoke-static {v12}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer; move-result-object v11 aput-object v11, v0, v10 invoke-static {v13}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer; move-result-object v10 aput-object v10, v0, v12 const/4 v10, 0x4 invoke-static {v10}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer; move-result-object v10 aput-object v10, v0, v13 .line 33 .local v0, "integers":[Ljava/lang/Integer; const/16 v10, 0x3a new-array v9, v10, [I fill-array-data v9, :array_1 .line 36 .local v9, "strings":[I array-length v4, v1 .line 37 .local v4, "length":I array-length v5, v3 .line 38 .local v5, "length1":I array-length v6, v9 .line 41 .local v6, "length2":I aget v7, v9, v14 .line 42 .local v7, "string":I aget v8, v3, v12 .line 45 .local v8, "string1":I aput v4, v9, v14 .line 46 aput v6, v3, v12 .line 47 return-void .line 29 :array_0 .array-data 4 0x1 0x2 0x3 .end array-data .line 33 :array_1 .array-data 4 0x1 0x2 0x3 0x4 0x5 0x6 0x5 0x6 0x6 0x6 0x6 0x6 0x6 0x7 0x7 0x8 0x8 0x8 0x8 0x8 0x1 0x1 0x1 0x3 0x3 0x5 0x6 0x36 0x5 0x6 0x38 0x237 0x43 0x6 0x22 0x2d 0x2d 0x6 0x38 0x39 0x2d 0x2d 0x5 0x38 0x38 0x7 0x22 0x21f 0x21f 0x6 0x38 0x38 0x2d 0x4 0x36 0x5 0x2d 0x38 .end array-data .end method
throw vAA:拋出vAA寄存器中指定類型的異常
private void throw2() { try { throw new Exception("test throw runtime exception"); } catch (Exception e) { e.printStackTrace(); } } private void throw1() { throw new RuntimeException("test throw runtime exception"); }
.method private throw1()V .locals 2 .prologue .line 38 new-instance v0, Ljava/lang/RuntimeException; const-string v1, "test throw runtime exception" invoke-direct {v0, v1}, Ljava/lang/RuntimeException;->(Ljava/lang/String;)V throw v0 .end method .method private throw2()V .locals 3 .prologue .line 31 :try_start_0 new-instance v1, Ljava/lang/Exception; const-string v2, "test throw runtime exception" invoke-direct {v1, v2}, Ljava/lang/Exception;-> (Ljava/lang/String;)V throw v1 :try_end_0 .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0 .line 32 :catch_0 move-exception v0 .line 33 .local v0, "e":Ljava/lang/Exception; invoke-virtual {v0}, Ljava/lang/Exception;->printStackTrace()V .line 35 return-void .end method
用於從當前地址跳轉到指定的偏移處,提供了三種指令:無條件(goto),分支跳轉(switch),條件跳轉(if)
goto +AA:無條件跳轉到指定偏移處,AA不能為0
goto/16 +AAAA
goto/32 +AAAAAAAA
packed-switch vAA, +BBBBBBBB:分支跳轉,vAA寄存器為switch分支需要判斷的值
if-test vA, vB, +CCCC 條件跳轉指令,比較vA寄存器與vB寄存器的值,如果比較結果滿足就跳轉到CCCC指定的偏移處,不能為0,有以下幾條:
if-eq:if(vA==vB)
if-ne:vA!=vB
if-lt:vA
private void testIfz() { int a = 3; if (a == 0) { } else { } if (a != 0) { } else { } if (a < 0) { } else { } if (a > 0) { } else { } if (a <= 0) { } else { } if (a >= 0) { } else { } if (a < 5) { Log.d("TAG", "<5"); } else if (a > 5) { Log.d("TAG", ">5"); } else { Log.d("TAG", "=5"); } } private void testIf() { int a = 2; int b = 3; if (a == b) { } else { } if (a != b) { } else { } if (a < b) { } else { } if (a > b) { } else { } if (a <= b) { } else { } if (a >= b) { } else { } }
.method private testIf()V .locals 2 .prologue .line 69 const/4 v0, 0x2 .line 70 .local v0, "a":I const/4 v1, 0x3 .line 71 .local v1, "b":I if-ne v0, v1, :cond_0 .line 76 :cond_0 if-eq v0, v1, :cond_1 .line 81 :cond_1 if-ge v0, v1, :cond_2 .line 86 :cond_2 if-le v0, v1, :cond_3 .line 91 :cond_3 if-gt v0, v1, :cond_4 .line 96 :cond_4 if-lt v0, v1, :cond_5 .line 102 :cond_5 return-void .end method .method private testIfz()V .locals 3 .prologue const/4 v1, 0x5 .line 27 const/4 v0, 0x3 .line 28 .local v0, "a":I if-nez v0, :cond_0 .line 33 :cond_0 if-eqz v0, :cond_1 .line 38 :cond_1 if-gez v0, :cond_2 .line 43 :cond_2 if-lez v0, :cond_3 .line 48 :cond_3 if-gtz v0, :cond_4 .line 53 :cond_4 if-ltz v0, :cond_5 .line 59 :cond_5 if-ge v0, v1, :cond_6 .line 60 const-string v1, "TAG" const-string v2, "<5" invoke-static {v1, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 66 :goto_0 return-void .line 61 :cond_6 if-le v0, v1, :cond_7 .line 62 const-string v1, "TAG" const-string v2, ">5" invoke-static {v1, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I goto :goto_0 .line 64 :cond_7 const-string v1, "TAG" const-string v2, "=5" invoke-static {v1, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I goto :goto_0 .end method
用於對兩個寄存器的值比較
cmpkind vAA, vBB, vCC:vBB和vCC為要比較的值,結果放到vAA中
cmpl-float:單精度,vBB大於vCC,vAA=-1,等於vAA=0,小於vAA=1
cmpg-float:單精度,vBB大於vCC,vAA=1,等於vAA=0,小於vAA=-1
cmpl-double:雙精度
cmpg-double:雙精度
cmp-long:長整形
private void testCmpLong() { long a = 13; long b = 12; if (a < b) { Log.d("TAG", "<"); } else if (a > b) { Log.d("TAG", ">"); } else { Log.d("TAG", "="); } } private void testCmpDouble() { double a = 13.4; double b = 11.4; if (a < b) { Log.d("TAG", "<"); } else if (a > b) { Log.d("TAG", ">"); } else { Log.d("TAG", "="); } } private void testCmpFloat() { float a = 13.4F; float b = 10.4F; if (a < b) { Log.d("TAG", "<"); } else if (a > b) { Log.d("TAG", ">"); } else { Log.d("TAG", "="); } }
.method private testCmpDouble()V .locals 6 .prologue .line 46 const-wide v0, 0x402acccccccccccdL # 13.4 .line 47 .local v0, "a":D const-wide v2, 0x4026cccccccccccdL # 11.4 .line 48 .local v2, "b":D cmpg-double v4, v0, v2 if-gez v4, :cond_0 .line 49 const-string v4, "TAG" const-string v5, "<" invoke-static {v4, v5}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 55 :goto_0 return-void .line 50 :cond_0 cmpl-double v4, v0, v2 if-lez v4, :cond_1 .line 51 const-string v4, "TAG" const-string v5, ">" invoke-static {v4, v5}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I goto :goto_0 .line 53 :cond_1 const-string v4, "TAG" const-string v5, "=" invoke-static {v4, v5}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I goto :goto_0 .end method .method private testCmpFloat()V .locals 4 .prologue .line 58 const v0, 0x41566666 # 13.4f .line 59 .local v0, "a":F const v1, 0x41266666 # 10.4f .line 60 .local v1, "b":F cmpg-float v2, v0, v1 if-gez v2, :cond_0 #>= .line 61 const-string v2, "TAG" const-string v3, "<" invoke-static {v2, v3}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 67 :goto_0 return-void .line 62 :cond_0 cmpl-float v2, v0, v1 if-lez v2, :cond_1 #<= .line 63 const-string v2, "TAG" const-string v3, ">" invoke-static {v2, v3}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I goto :goto_0 .line 65 :cond_1 const-string v2, "TAG" const-string v3, "=" invoke-static {v2, v3}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I goto :goto_0 .end method .method private testCmpLong()V .locals 6 .prologue .line 34 const-wide/16 v0, 0xd .line 35 .local v0, "a":J const-wide/16 v2, 0xc .line 36 .local v2, "b":J cmp-long v4, v0, v2 if-gez v4, :cond_0 .line 37 const-string v4, "TAG" const-string v5, "<" invoke-static {v4, v5}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 43 :goto_0 return-void .line 38 :cond_0 cmp-long v4, v0, v2 if-lez v4, :cond_1 .line 39 const-string v4, "TAG" const-string v5, ">" invoke-static {v4, v5}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I goto :goto_0 .line 41 :cond_1 const-string v4, "TAG" const-string v5, "=" invoke-static {v4, v5}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I goto :goto_0 .end method
用來對 對象實例的字段進行讀寫操作。字段類型可以是Java中有效的類型,對於實例字段和靜態字段有兩類指令:
iget,iput對實例字段進行讀,寫
sget,sput對靜態字段
會根據類型不同添加不同的後綴
iget,iget-wide,iget-object,iget-boolean,iget-byte,iget-char,iget-short
iput,iput-wide,iput-object,iput-boolean,iput-byte,iput-char,iput-short
sget,sget-wide,sget-object,sget-boolean,sget-byte,sget-char,sget-short
…
private void testInstanceFieldOperator() { //write InstanceObject instanceObject = new InstanceObject(); instanceObject.aInt=1; instanceObject.aLong=12454L; instanceObject.aFloat=12344.45F; instanceObject.aDouble=123546.2; instanceObject.object=new Object(); instanceObject.aBoolean=true; instanceObject.aByte=3; instanceObject.aChar='c'; instanceObject.aShort=1; Log.d("TAG",String.valueOf(instanceObject.aInt)); Log.d("TAG",String.valueOf(instanceObject.aLong)); Log.d("TAG",String.valueOf(instanceObject.aFloat)); Log.d("TAG",String.valueOf(instanceObject.aDouble)); Log.d("TAG",String.valueOf(instanceObject.object)); Log.d("TAG",String.valueOf(instanceObject.aBoolean)); Log.d("TAG",String.valueOf(instanceObject.aByte)); Log.d("TAG",String.valueOf(instanceObject.aChar)); Log.d("TAG",String.valueOf(instanceObject.aShort)); } private void testStatusFieldOperator() { //write StatusObject.aInt=1; StatusObject.aLong=12454L; StatusObject.aFloat=12344.45F; StatusObject.aDouble=123546.2; StatusObject.object=new Object(); StatusObject.aBoolean=true; StatusObject.aByte=3; StatusObject.aChar='c'; StatusObject.aShort=1; Log.d("TAG",String.valueOf(StatusObject.aInt)); Log.d("TAG",String.valueOf(StatusObject.aLong)); Log.d("TAG",String.valueOf(StatusObject.aFloat)); Log.d("TAG",String.valueOf(StatusObject.aDouble)); Log.d("TAG",String.valueOf(StatusObject.object)); Log.d("TAG",String.valueOf(StatusObject.aBoolean)); Log.d("TAG",String.valueOf(StatusObject.aByte)); Log.d("TAG",String.valueOf(StatusObject.aChar)); Log.d("TAG",String.valueOf(StatusObject.aShort)); }
.method private testInstanceFieldOperator()V .locals 5 .prologue const/4 v4, 0x1 .line 30 new-instance v0, Lcom/woblog/testsmali/InstanceObject; invoke-direct {v0}, Lcom/woblog/testsmali/InstanceObject;->()V .line 31 .local v0, "instanceObject":Lcom/woblog/testsmali/InstanceObject; iput v4, v0, Lcom/woblog/testsmali/InstanceObject;->aInt:I .line 32 const-wide/16 v2, 0x30a6 iput-wide v2, v0, Lcom/woblog/testsmali/InstanceObject;->aLong:J .line 33 const v1, 0x4640e1cd iput v1, v0, Lcom/woblog/testsmali/InstanceObject;->aFloat:F .line 34 const-wide v2, 0x40fe29a333333333L # 123546.2 iput-wide v2, v0, Lcom/woblog/testsmali/InstanceObject;->aDouble:D .line 35 new-instance v1, Ljava/lang/Object; invoke-direct {v1}, Ljava/lang/Object;-> ()V iput-object v1, v0, Lcom/woblog/testsmali/InstanceObject;->object:Ljava/lang/Object; .line 36 iput-boolean v4, v0, Lcom/woblog/testsmali/InstanceObject;->aBoolean:Z .line 37 const/4 v1, 0x3 iput-byte v1, v0, Lcom/woblog/testsmali/InstanceObject;->aByte:B .line 38 const/16 v1, 0x63 iput-char v1, v0, Lcom/woblog/testsmali/InstanceObject;->aChar:C .line 39 iput-short v4, v0, Lcom/woblog/testsmali/InstanceObject;->aShort:S .line 41 const-string v1, "TAG" iget v2, v0, Lcom/woblog/testsmali/InstanceObject;->aInt:I invoke-static {v2}, Ljava/lang/String;->valueOf(I)Ljava/lang/String; move-result-object v2 invoke-static {v1, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 42 const-string v1, "TAG" iget-wide v2, v0, Lcom/woblog/testsmali/InstanceObject;->aLong:J invoke-static {v2, v3}, Ljava/lang/String;->valueOf(J)Ljava/lang/String; move-result-object v2 invoke-static {v1, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 43 const-string v1, "TAG" iget v2, v0, Lcom/woblog/testsmali/InstanceObject;->aFloat:F invoke-static {v2}, Ljava/lang/String;->valueOf(F)Ljava/lang/String; move-result-object v2 invoke-static {v1, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 44 const-string v1, "TAG" iget-wide v2, v0, Lcom/woblog/testsmali/InstanceObject;->aDouble:D invoke-static {v2, v3}, Ljava/lang/String;->valueOf(D)Ljava/lang/String; move-result-object v2 invoke-static {v1, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 45 const-string v1, "TAG" iget-object v2, v0, Lcom/woblog/testsmali/InstanceObject;->object:Ljava/lang/Object; invoke-static {v2}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String; move-result-object v2 invoke-static {v1, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 46 const-string v1, "TAG" iget-boolean v2, v0, Lcom/woblog/testsmali/InstanceObject;->aBoolean:Z invoke-static {v2}, Ljava/lang/String;->valueOf(Z)Ljava/lang/String; move-result-object v2 invoke-static {v1, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 47 const-string v1, "TAG" iget-byte v2, v0, Lcom/woblog/testsmali/InstanceObject;->aByte:B invoke-static {v2}, Ljava/lang/String;->valueOf(I)Ljava/lang/String; move-result-object v2 invoke-static {v1, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 48 const-string v1, "TAG" iget-char v2, v0, Lcom/woblog/testsmali/InstanceObject;->aChar:C invoke-static {v2}, Ljava/lang/String;->valueOf(C)Ljava/lang/String; move-result-object v2 invoke-static {v1, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 49 const-string v1, "TAG" iget-short v2, v0, Lcom/woblog/testsmali/InstanceObject;->aShort:S invoke-static {v2}, Ljava/lang/String;->valueOf(I)Ljava/lang/String; move-result-object v2 invoke-static {v1, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 50 return-void .end method .method private testStatusFieldOperator()V .locals 4 .prologue const/4 v2, 0x1 .line 54 sput v2, Lcom/woblog/testsmali/StatusObject;->aInt:I .line 55 const-wide/16 v0, 0x30a6 sput-wide v0, Lcom/woblog/testsmali/StatusObject;->aLong:J .line 56 const v0, 0x4640e1cd sput v0, Lcom/woblog/testsmali/StatusObject;->aFloat:F .line 57 const-wide v0, 0x40fe29a333333333L # 123546.2 sput-wide v0, Lcom/woblog/testsmali/StatusObject;->aDouble:D .line 58 new-instance v0, Ljava/lang/Object; invoke-direct {v0}, Ljava/lang/Object;-> ()V sput-object v0, Lcom/woblog/testsmali/StatusObject;->object:Ljava/lang/Object; .line 59 sput-boolean v2, Lcom/woblog/testsmali/StatusObject;->aBoolean:Z .line 60 const/4 v0, 0x3 sput-byte v0, Lcom/woblog/testsmali/StatusObject;->aByte:B .line 61 const/16 v0, 0x63 sput-char v0, Lcom/woblog/testsmali/StatusObject;->aChar:C .line 62 sput-short v2, Lcom/woblog/testsmali/StatusObject;->aShort:S .line 64 const-string v0, "TAG" sget v1, Lcom/woblog/testsmali/StatusObject;->aInt:I invoke-static {v1}, Ljava/lang/String;->valueOf(I)Ljava/lang/String; move-result-object v1 invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 65 const-string v0, "TAG" sget-wide v2, Lcom/woblog/testsmali/StatusObject;->aLong:J invoke-static {v2, v3}, Ljava/lang/String;->valueOf(J)Ljava/lang/String; move-result-object v1 invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 66 const-string v0, "TAG" sget v1, Lcom/woblog/testsmali/StatusObject;->aFloat:F invoke-static {v1}, Ljava/lang/String;->valueOf(F)Ljava/lang/String; move-result-object v1 invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 67 const-string v0, "TAG" sget-wide v2, Lcom/woblog/testsmali/StatusObject;->aDouble:D invoke-static {v2, v3}, Ljava/lang/String;->valueOf(D)Ljava/lang/String; move-result-object v1 invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 68 const-string v0, "TAG" sget-object v1, Lcom/woblog/testsmali/StatusObject;->object:Ljava/lang/Object; invoke-static {v1}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String; move-result-object v1 invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 69 const-string v0, "TAG" sget-boolean v1, Lcom/woblog/testsmali/StatusObject;->aBoolean:Z invoke-static {v1}, Ljava/lang/String;->valueOf(Z)Ljava/lang/String; move-result-object v1 invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 70 const-string v0, "TAG" sget-byte v1, Lcom/woblog/testsmali/StatusObject;->aByte:B invoke-static {v1}, Ljava/lang/String;->valueOf(I)Ljava/lang/String; move-result-object v1 invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 71 const-string v0, "TAG" sget-char v1, Lcom/woblog/testsmali/StatusObject;->aChar:C invoke-static {v1}, Ljava/lang/String;->valueOf(C)Ljava/lang/String; move-result-object v1 invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 72 const-string v0, "TAG" sget-short v1, Lcom/woblog/testsmali/StatusObject;->aShort:S invoke-static {v1}, Ljava/lang/String;->valueOf(I)Ljava/lang/String; move-result-object v1 invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 73 return-void .end method
在方法調用者我們可以看到有:
invoke-super {p0, p1}, Lcom/woblog/testsmali/BaseActivity;->onCreate(Landroid/os/Bundle;)V invoke-virtual {p0, v0}, Lcom/woblog/testsmali/MainActivity;->setContentView(I)V invoke-direct {p0}, Lcom/woblog/testsmali/MainActivity;->initMove()V invoke-static {}, Lcom/woblog/testsmali/TimeUtil;->getCurrentTime()J invoke-interface {v0}, Lcom/woblog/testsmali/ICallback;->onSuccess()V
數據轉換指令用於將一種數據類型轉換為另一個類型,unop vA, vB:寄存器存儲要轉換的數據,vA存儲轉換後的數據
neg-int:整形求補
not-int:整形求反
neg-long:長整型求補
not-long:長整型求反
neg-float:單精度求補
not-float:
neg-double:
not-double:
int-to-long:整型轉為長整型
int-to-float:整型轉單精度浮點型
int-to-double:整型轉雙精度浮點型
int-to-byte:整型轉字節型
int-to-char:整型轉字符串
int-to-short:整型轉短整型
long-to-int
long-to-float
long-to-double
float-to-int
float-to-long
float-to-double
double-to-int
double-to-long
double-to-float
private void testConvert() { int i1=13; //int 轉其他類型 long l1 = i1; float f1 = i1; double d1 = i1; byte b1 = (byte) i1; char c1 = (char) i1; short s1 = (short) i1; //long 轉其他類型 long l2 = 234444556576L; int i2 = (int) l2; float f2 = l2; double d2 = l2; //float 轉其他類型 float f10 =234399.9F; int i10 = (int) f10; long l10 = (long) f10; double d10 = f10; //double 轉其他類型 double d20 = 123344445.324; int i20 = (int) d20; long l20 = (long) d20; float f20 = (float) d20; }
.method private testConvert()V .locals 29 .prologue .line 30 const/16 v16, 0xd .line 33 .local v16, "i1":I move/from16 v0, v16 int-to-long v0, v0 move-wide/from16 v20, v0 .line 34 .local v20, "l1":J move/from16 v0, v16 int-to-float v12, v0 .line 35 .local v12, "f1":F move/from16 v0, v16 int-to-double v4, v0 .line 37 .local v4, "d1":D move/from16 v0, v16 int-to-byte v2, v0 .line 38 .local v2, "b1":B move/from16 v0, v16 int-to-char v3, v0 .line 39 .local v3, "c1":C move/from16 v0, v16 int-to-short v0, v0 move/from16 v28, v0 .line 42 .local v28, "s1":S const-wide v24, 0x3695fc0920L .line 43 .local v24, "l2":J move-wide/from16 v0, v24 long-to-int v0, v0 move/from16 v18, v0 .line 44 .local v18, "i2":I move-wide/from16 v0, v24 long-to-float v14, v0 .line 45 .local v14, "f2":F move-wide/from16 v0, v24 long-to-double v8, v0 .line 48 .local v8, "d2":D const v13, 0x4864e7fa # 234399.9f .line 49 .local v13, "f10":F float-to-int v0, v13 move/from16 v17, v0 .line 50 .local v17, "i10":I float-to-long v0, v13 move-wide/from16 v22, v0 .line 51 .local v22, "l10":J float-to-double v6, v13 .line 54 .local v6, "d10":D const-wide v10, 0x419d6858f54bc6a8L # 1.23344445324E8 .line 55 .local v10, "d20":D double-to-int v0, v10 move/from16 v19, v0 .line 56 .local v19, "i20":I double-to-long v0, v10 move-wide/from16 v26, v0 .line 57 .local v26, "l20":J double-to-float v15, v10 .line 58 .local v15, "f20":F return-void .end method
算術運算:加,減,乘,除,模,移位等
邏輯運算:與,或,非,異或等
binop vAA, vBB, vCC:將vBB寄存器與vCC寄存器進行運算,結果保存到vAA
上面的指令會根據數據類型的不同在基礎後面添加數據類型後綴,如:-int或-long
add-type vBB:vBB寄存器與vCC寄存器值進行加法運算,+
sub-type vBB:-
mul-type vBB:*
div-type vBB:/
rem-type vBB:%
and-type vBB:and
or-type vBB:or
xor-type vBB:xor
shl-type vBB:左移vCC位,<<
shr-type vBB:右移vCC位,>>
ushr-type vBB:無符號>>
其中type可以為int,long,float,double
binop/2addr vA, vB:將vA寄存器與vB寄存器進行運算,結果保存到vA
binop/lit16 vA, vB, #+CCCC:將vB寄存器與常量CCCC進行運算,結果保存到vA
binop/lit8 vAA, vBB, #+CC:將vBB寄存器與常量CC進行運行,結果保存到vAA
首先寫一個基本框架
.class public LHelloWorld; #定義類名 .super Ljava/lang/Object; #定義父類 .method public static main([Ljava/lang/String;)V #聲明靜態的main函數 .locals 4 #使用的寄存器個數,包括一個參數寄存器 .param p0, "args" #一個參數 .prologue #代碼起始指令 # 這裡是代碼主體 return-void .end method
完整版如下:
.class public LHelloWorld; #定義類名 .super Ljava/lang/Object; #定義父類 .method public static main([Ljava/lang/String;)V #聲明靜態的main函數 .locals 4 #使用的寄存器個數,包括一個參數寄存器 .param p0, "args" #一個參數 .prologue #代碼起始指令 const-string v1, "Hello World" sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream; invoke-virtual {v0,v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V return-void .end method
我們去官網下載smali.jar,然後運行
java -jar smali.jar -o classes.dex HelloWorld.smali
編譯完後我們把classes.dex push到手機裡面
adb push classes.dex /data/local/
dalvikvm -cp /data/local/classes.dex HelloWorld
加強版本
.class public LHelloWorld; #定義類名 .super Ljava/lang/Object; #定義父類 .method public static main([Ljava/lang/String;)V #聲明靜態的main函數 .locals 10 #使用的寄存器個數,包括一個參數寄存器 .param p0, "args" #一個參數 .prologue #代碼起始指令 sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream; # 空指令 nop nop nop # 數據定義指令 const/4 v2, 0x3 const/16 v3, 0xffff ##不能大於65535 #大於65535用-wide const-wide v4, 0x10000 # 定義一個類 類型 const-class v5, Ljava/lang/String; # 數據操作指令 move v6, v2 new-instance v7, Ljava/lang/StringBuilder; invoke-direct {v7}, Ljava/lang/StringBuilder;->()V const-string v8, "\u8fd9\u662f\u4e00\u4e2a\u624b\u5199\u7684\u0073\u006d\u0061\u006c\u0069\u5b9e\u4f8b" invoke-virtual {v7, v8}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v7 invoke-virtual {v7}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; move-result-object v9 invoke-virtual {v0, v9}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V # 打印字符串 const-string v1, "Hello World" invoke-virtual {v0,v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V return-void .end method
下一篇文章我們講解odex文件格式
只有簡單的三步,官網寫的非常簡明全面,非常佩服 【准備】 1. Eclipse(Indigo) 2. ADT: 這個不說了,無非就是eclipse添加個an
在Android中,如果我們要展示的圖片是存儲在網絡上的時候,我們就必須通過HttpClient或者HttpUrlConnection這兩個類來進行關於網絡方面的操作,比
圓角按鈕,或布局可以在xml文件中實現,但也可以使用圖片直接達到所需的效果,以前版本的微信就使用了這種方法。 實現效果圖: 不得不說,這種做法還是比較方便的。 源
現在大家越來越多的使用AndroidStudio進行Android開發,那麼今天就和大家一起交流一下AndroidStudio開發NDK的配置方法。AndroidStud