Smali文件結構解
Smali文件與java中的類是一一對應的,包括內部類和匿名內部類也會生成對應的smali文件(典型的比如實現某個接口的匿名內部類),所以你會看到.smali文件比.java文件更多。
smali文件是由Dalvik指令組成的,它有自己的一套規則,它的指令都是以“.”開頭,常用的指令如下:
smali文件是由Dalvik指令組成的,它有自己的一套規則,它的指令都是以“.”開頭,常用的指令如下:
指令
說明
.class
包名+類名
包名+類名
.super
父類類名
.source
源文件名稱
.implements
接口實現
.field
定義字段
.method/.end method
方法的開始與結束
.locals
方法內使用的v開口的寄存器個數
.prologue
表示方法中代碼的開始處
.line
對應java中的行數
.param
指定了方法的參數
.paramter
和.paramter含義相同
.param
指定了方法的參數
.annotation/.end annotation
注解的開始和結束
現在來看下smali文件的結構:
1.頭文件
格式如下:
.class <訪問權限修飾符> [非權限修飾符] <類名>
.super <父類名>
.source <源文件名稱>
1234
.super <父類名>
.source <源文件名稱>
1234
訪問權限修飾符即所謂的public,protected,private,而非權限修飾符則指的是final,abstract,static,兩者都可以為空。
舉例如下:
舉例如下:
.class public final Llutey/FTPServer/preferences/PreferencesFactory;
.super Ljava/lang/Object;
.source "PreferencesFactory.java"
1234
.super Ljava/lang/Object;
.source "PreferencesFactory.java"
1234
如果原java代碼有經過混淆,那一般.class里面的類名和.source的源文件名會不一樣,以下是經過混淆的(類名正常是xxx/PreferencesFactory,混淆以后變成xxx/d):
.class public final Llutey/FTPServer/preferences/d;
.super Ljava/lang/Object;
.source "PreferencesFactor123
.super Ljava/lang/Object;
.source "PreferencesFactor123
2.接口實現
格式如下:
#interfaces
.implements <接口名稱>12
.implements <接口名稱>12
舉例如下:
# interfaces
.implements Landroid/view/View$OnClickListener;12
.implements Landroid/view/View$OnClickListener;12
其中# interfaces為注釋
3.注解
如果一個類中使用了注解,就會出現.annotation,格式如下:
#annotations
.annotation [注解的屬性] <注解類名>
[注解字段=值]
...
.end annotation12345
.annotation [注解的屬性] <注解類名>
[注解字段=值]
...
.end annotation12345
舉例如下:
# annotations
.annotation build Landroid/annotation/TargetApi;
value = 0xb
.end annotation1234
.annotation build Landroid/annotation/TargetApi;
value = 0xb
.end annotation1234
其中# annotations為注釋
4.變量定義
使用.field描述字段的定義,分為靜態變量和普通變量兩種:
靜態變量
格式如下:
#static fields
.field <訪問權限> static [修飾詞] <字段名>:<變量類型>12
.field <訪問權限> static [修飾詞] <字段名>:<變量類型>12
使用# static fields注釋,並加了static修飾符,
舉例說明:
smali:
smali:
# static fields
.field public static mStr:Ljava/lang/String;12
.field public static mStr:Ljava/lang/String;12
java:
public static final String mStr;1
普通變量
格式如下:
#instance fields
.field <訪問權限修飾符> [非權限修飾符] <變量名>:<變量類型>12
.field <訪問權限修飾符> [非權限修飾符] <變量名>:<變量類型>12
使用# instance fields注釋,
舉例說明:
smali:
smali:
.field private bool:Z1
java:
private boolean bool;1
5.方法描述
smali中的方法以.method/.end method進行描述,有分兩種方法,一種是直接方法,一種是虛方法,
什么事直接方法和虛方法呢?直接方法就是不能被覆寫的方法,包括用static,private修飾的方法,虛方法表示可以被覆寫的方法,包括public,protected修飾的方法。
兩者在smali中的注釋分別是直接方法(#direct methods),虛方法(#virtual methods),一般直接方法在smali文件的前半部分,虛方法在后半部分。
方法的格式如下:
什么事直接方法和虛方法呢?直接方法就是不能被覆寫的方法,包括用static,private修飾的方法,虛方法表示可以被覆寫的方法,包括public,protected修飾的方法。
兩者在smali中的注釋分別是直接方法(#direct methods),虛方法(#virtual methods),一般直接方法在smali文件的前半部分,虛方法在后半部分。
方法的格式如下:
#direct methods/#virtual methods
.method <訪問權限修飾符> [非訪問權限修飾符] <方法原型>
<.locals>
[.parameter]
[.prologue]
[.line]
<代碼邏輯>
.end12345678
.method <訪問權限修飾符> [非訪問權限修飾符] <方法原型>
<.locals>
[.parameter]
[.prologue]
[.line]
<代碼邏輯>
.end12345678
其中.parameter,.prologue,.line是可選的。
舉例說明:
舉例說明:
# virtual methods
.method public final onClick(Landroid/view/View;)V
.locals 1
.method public final onClick(Landroid/view/View;)V
.locals 1
.prologue
.line 71
iget-object v0, p0, Llutey/FTPServer/preferences/sdk11/pre/a;->a:Llutey/FTPServer/preferences/sdk11/pre/FTPServerPreferences;
.line 71
iget-object v0, p0, Llutey/FTPServer/preferences/sdk11/pre/a;->a:Llutey/FTPServer/preferences/sdk11/pre/FTPServerPreferences;
invoke-static {v0}, Llutey/FTPServer/preferences/sdk11/pre/FTPServerPreferences;->a(Llutey/FTPServer/preferences/sdk11/pre/FTPServerPreferences;)V
.line 72
return-void
.end method12345678910111213
return-void
.end method12345678910111213
注意幾個特殊的方法:
.method xxx constructor <clinit>()V //類中final變量的初始化
.method xxx constructor <init>()V //類中的構造行數
.method static synthetic methodName(xxxx)V //加synthetic修飾符的方法,synthetic是合成的意思,即這個方法在原java代碼里面是沒有的,是在java編譯成Dalvik字節碼的時候合成的,后續會詳細分析這類方法123
.method xxx constructor <init>()V //類中的構造行數
.method static synthetic methodName(xxxx)V //加synthetic修飾符的方法,synthetic是合成的意思,即這個方法在原java代碼里面是沒有的,是在java編譯成Dalvik字節碼的時候合成的,后續會詳細分析這類方法123
方法中具體的語法在文章的后半部分詳細為您說明。
smali數據類型
Dalvik字節碼和Java一樣,都只有兩種數據類型:基本類型和引用類型,8中基本數據類型,對象和數組是引用類型,Dalvik字節碼和Jvm中對數據類型的描述是一致的,
對於基本類型和無返回類型用一個大寫字母表示,對象類型用一個大寫字母L加對象的全限定名表示,如Ljava/lang/String表示字符串對象類型,
一維數組用一個“[”加數據類型或對象類型表示.
java數據類型和Dalvik字節碼的數據類型一一對應,對應關系如下表:
對於基本類型和無返回類型用一個大寫字母表示,對象類型用一個大寫字母L加對象的全限定名表示,如Ljava/lang/String表示字符串對象類型,
一維數組用一個“[”加數據類型或對象類型表示.
java數據類型和Dalvik字節碼的數據類型一一對應,對應關系如下表:
java類型
smali描述符
boolean
Z
Z
byte
B
short
S
char
C
int
I
long
L
float
F
double
D
void
V
對象類型
L
數組類型
[
基本數據類型
Z,B,S,C,I,L,F,D為基本數據類型,從上表可以看出,Dalvik字節碼基本類型的描述符基本上是java基本類型的首字母,除了boolean對應為Z外
對象類型
L加上類或者接口的全稱表示對象類型,即Lpackage/objectName,如String類型描述符為Ljava/lang/String,包com.biyou下面的test類的類型描述符為Lcom/biyou/test
數組類型
基本類型的數組為”[“加上基本類型描述符來表示,一維數組前面是一個”[“,多一個維度前面多加一個”[“,比如int類型,一維是:[I,二維是:[[I,依次類推。
對象類型的數組為”[“加上對象類型表示符來表示,如String類型表示為:[Ljava/lang/String。
對象類型的數組為”[“加上對象類型表示符來表示,如String類型表示為:[Ljava/lang/String。
smali語法
smali的語法跟匯編語言有點類似,但沒有匯編那么復雜,可以很輕松的看懂,推薦使用source insight來看。
變量的描述
格式為:
對象類型描述符->變量名:類型描述符;1
舉例說明:
Lcom/biyou/test;->count:I //基本類型
Lcom/biyou/test;->str:Ljava/lang/String //對象類型12
Lcom/biyou/test;->str:Ljava/lang/String //對象類型12
Dalvik對變量的描述都會指明變量定義的和變量的類型,如例子中的count變量的描述,說明它定義在com.biyou.test類,是int類型的變量
方法的描述
格式為:
對象類型描述符->方法名(參數類型描述符)返回值類型描述符;1
下面我們通過幾個例子來說明,以java.lang.String為例:
java方法:public char charAt(int index){...}
Davilk描述:Ljava/lang/String;->charAt(I)C
Davilk描述:Ljava/lang/String;->charAt(I)C
java方法:public void getChars(int srcBegin,int srcEnd,char dst[],int dstBegin){...}
Davilk描述:Ljava/lang/String;->getChars(II[CI)V
Davilk描述:Ljava/lang/String;->getChars(II[CI)V
java方法:public boolean equals(Object anObject){...}
Davilk描述:Ljava/lang/String;->equals(Ljava/lang/Object)Z12345678
Davilk描述:Ljava/lang/String;->equals(Ljava/lang/Object)Z12345678
Dalvik指令集
掌握以上的字段和方法的描述,只能說我們懂了如何描述一個字段和方法,而關於方法中具體的邏輯則需要了解Dalvik中的指令集.因為Dalvik是基於寄存器的架構的,因此指令集和JVM中的指令集區別較大,反而更類似x86的中的匯編指令。
1.空操作指令
空操作指令的助記符為nop,它的值為00,通常nop指令被用來作對齊代碼之用,無實際操作。
2.數據定義指令
數據定義指令用於定義代碼中使用的常量,字符串,類等數據,基礎字節碼是const
指令
描述
const/4 vA,#+B
將數值符號擴展為32后賦值給寄存器vA
將數值符號擴展為32后賦值給寄存器vA
const/16 vAA, #+BBBB
將數據符號擴展為32位后賦給寄存器vAA
const vAA, #+BBBBBBBB
將數值賦給寄存器vAA
const/high16 vAA, #+BBBB0000
將數值右邊零擴展為32位后賦給寄存器vAA
const-wide/16 vAA,#+BBBB
將數值符號擴展為64位后賦值個寄存器對vAA
const-wide/32 vAA,#+BBBB
將數值符號擴展為64位后賦值個寄存器對vAA
const-wide vAA, #+BBBBBBBBBBBBBBBB
將數值賦給寄存器對vAA
const-wide/high16 vAA, #+BBBB000000000000
將數值右邊零擴展為64位后賦給寄存器對vAA
const-string vAA,string@BBBB
通過字符串索引高走字符串賦值給寄存器vAA
const-string/jumbo vAA, string@BBBBBBBB
通過字符串索引(較大)構造一個字符串並賦給寄存器vAA
const-class vAA,type@BBBB
通過類型索引獲取一個類的引用賦值給寄存器vAA
const-class/jumbo vAAAA, type@BBBBBBBB
通過給定的類型索引獲取一個類引用並賦給寄存器vAAAA。這條指令占用兩個字節,值為0xooff(Android4.0中新增的指令)
3.鎖指令
鎖指令多用在多線程程序中對同一對象的操作。Dalvik指令集中有兩條鎖指令:
monitor-enter vAA:為指定的對象獲取鎖。
monitor-exit vAA:釋放指定的對象的鎖。12
monitor-exit vAA:釋放指定的對象的鎖。12
如java的com.biyou.test類需要需要加鎖:
java為:
java為:
synchronized (test.class)
{
...
}1234
{
...
}1234
smali為:
const-class v0, Lcom/biyou/test;
monitor-enter v0
...
monitor-exit v01234
monitor-enter v0
...
monitor-exit v01234
4.變量操作指令
字段操作指令表示對對象字段進行設值和取值操作,就像是你在代碼中長些的set和get方法.基本指令是iput-type,iget-type,sput-type,sget-type.type表示數據類型.
普通字段讀寫操作
前綴是i的iput-type和iget-type指令用於字段的讀寫操作.
指令
描述
iget-object vAA,vBB,filed_id
讀取vAA寄存器中的對象中的filed_id對象的引用值給vBB寄存器
讀取vAA寄存器中的對象中的filed_id對象的引用值給vBB寄存器
iget-boolean vAA,vBB,filed_id
讀取vAA寄存器中的對象中的filed_id的值給vBB寄存器
iget-wide vAA,vBB,filed_id
讀取vAA寄存器中的對象中的filed_id的值給vBB寄存器
iget vAA,vBB,filed_id
讀取vAA寄存器中的對象中的filed_id的值給vBB寄存器
iput-object vAA,vBB,filed_id
把vAA寄存器指向的對象的引用賦值給vBB寄存器中的filed_id對象
iput-boolean vAA,vBB,filed_id
把vAA寄存器的值給vBB寄存器中的boolean類型
iput-wide vAA,vBB,filed_id
把vAA寄存器的值給vBB寄存器中的wide類型
iput vAA,vBB,filed_id
把vAA寄存器的值給vBB寄存器中的int類型
靜態字段讀寫操作
前綴是s的sput-type和sget-type指令用於靜態字段的讀寫操作
指令
描述
sget-object vAA,vBB,filed_id
讀取vAA寄存器中的對象中的filed_id對象的引用值給vBB寄存器
讀取vAA寄存器中的對象中的filed_id對象的引用值給vBB寄存器
sget-boolean vAA,vBB,filed_id
讀取vAA寄存器中的對象中的filed_id的值給vBB寄存器
sget-wide vAA,vBB,filed_id
讀取vAA寄存器中的對象中的filed_id的值給vBB寄存器
sget vAA,vBB,filed_id
讀取vAA寄存器中的對象中的filed_id的值給vBB寄存器
sput-object vAA,vBB,filed_id
把vAA寄存器指向的對象的引用賦值給vBB寄存器中的filed_id對象
sput-boolean vAA,vBB,filed_id
把vAA寄存器的值給vBB寄存器中的boolean類型
sput-wide vAA,vBB,filed_id
把vAA寄存器的值給vBB寄存器中的wide類型
sput vAA,vBB,filed_id
把vAA寄存器的值給vBB寄存器中的int類型
5.跳轉指令
跳轉指令用於從當前地址跳轉到指定的偏移處。Dalvik指令集中有三種跳轉指令:無條件跳轉(goto),分支跳轉(switch)與條件跳轉(if)。
goto +AA:無條件跳轉到指定偏移處,偏移量AA不能為0。
goto/16 +AAAA:無條件跳轉到指定偏移處,偏量AAAA不能為0。
goto/32 +AAAAAAAA:無條件跳轉到指定偏移處。
packed-switch vAA, +BBBBBBBB:分支跳轉指令。vAA寄存器為switch分支中需要判斷的值,BBBBBBBB指向一個packed-switch-payload格式的偏移表,表中的值是有規律遞增的。
sparse-switch vAA, +BBBBBBBB:分支跳轉指令。vAA寄存器為switch分支中需要判斷的值,BBBBBBBB指向一個sparse-switch-payload格式的偏移表,表中的值是無規律的偏移量。
if-test vA, vB, +CCCC:條件跳轉指令。比較vA寄存器與vB寄存器的值,如果比較結果滿足就跳轉到CCCC指定的偏移處。偏移量CCCC不能為0。if-test類型的指令有以下幾條:
if-eq:如果vA等於vB則跳轉。Java語法表示為“if(vA == vB)”
if-ne:如果vA不等於vB則跳轉。Java語法表示為“if(vA != vB)”
if-lt:如果vA小於vB則跳轉。Java語法表示為“if(vA < vB)”
if-ge:如果vA大於等於vB則跳轉。Java語法表示為“if(vA >= vB)”
if-gt:如果vA大於vB則跳轉。Java語法表示為“if(vA > vB)”
if-le:如果vA小於等於vB則跳轉。Java語法表示為“if(vA <= vB)”
if-testz vAA, +BBBB:條件跳轉指令。拿vAA寄存器與0比較,如果比較結果滿足或值為0時就跳轉到BBBB指定的偏移處。偏移量BBBB不能為0。if-testz類型的指令有以下幾條:
if-eqz:如果vAA為0則跳轉。Java語法表示為“if(vAA == 0)”
if-nez:如果vAA不為0則跳轉。Java語法表示為“if(vAA != 0)”
if-ltz:如果vAA小於0則跳轉。Java語法表示為“if(vAA < 0)”
if-gez:如果vAA大於等於0則跳轉。Java語法表示為“if(vAA >= 0)”
if-gtz:如果vAA大於0則跳轉。Java語法表示為“if(vAA > 0)”
if-lez:如果vAA小於等於0則跳轉。Java語法表示為“if(vAA <= 0)”
6.比較指令
比較指令用於對兩個寄存器的值(浮點型或長整型)進行比較。它的格式為“cmpkind vAA, vBB, vCC”,其中vBB寄存器與vCC寄存器是需要比較的兩個寄存器或寄存器對,比較的結果放到vAA寄存器。Dalvik指令集中共有5條比較指令:
cmpl-float vAA,vBB,vCC:比較兩個單精度浮點數。如果vBB寄存器大於vCC寄存器,結果為-1,相等則結果為0,小於的話結果為1
cmpg-float vAA,vBB,vCC:比較兩個單精度浮點數。如果vBB寄存器大於vCC寄存器,則結果為1,相等則結果為0,小於的話結果為-1
cmpl-double vAA,vBB,vCC:比較兩個雙精度浮點數。如果vBB寄存器對大於vCC寄存器對,則結果為-1,相等則結果為0,小於則結果為1
cmpg-double vAA,vBB,vCC:比較兩個雙精度浮點數。如果vBB寄存器對大於vCC寄存器對,則結果為1,相等則結果為0,小於的話,則結果為-1
cmp-long vAA,vBB,vCC:比較兩個長整型數。如果vBB寄存器大於vCC寄存器,則結果為1,相等則結果為0,小則結果為-1
7.數據轉換指令
數據轉換指令用於將一種類型的數值轉換成另一種類型。它的格式為“unop vA, vB”,vB寄存器或vB寄存器對存放需要轉換的數據,轉換后的結果保存在vA寄存器或vA寄存器對中。
•“neg-int”:對整型數求補。
•“not-int”:對整型數求反。
•“neg-long”:對長整型數求補。
•“not-long”:對長整型數求反。
•“neg-float”:對單精度浮點型數求補。
•“neg-double”:對雙精度浮點型數求補。
•“int-to-long”:將整型數轉換為長整型。
•“int-to-float”:將整型數轉換為單精度浮點型數。
•“int-to-dobule”:將整型數轉換為雙精度浮點數。
•“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”:將雙精度浮點數轉換為單精度浮點型。
•“int-to-byte”:將整型轉換為字節型。
•“int-to-char”:將整型轉換為字符型。
•“int-to-short”:將整型轉換為短整型。
8.數據運行指令
數據運算指令包括算術運算指令與邏輯運算指令。算術運算指令主要進行數值間如加,減,乘,除,模,移位等運算。邏輯運算指令主要進行數值間與,或,非,抑或等運算。數據運算指令有如下四類(數據運算時可能是在寄存器或寄存器對間進行,下面的指令作用講解時使用寄存器來描述):
•“binop vAA, vBB, vCC”:將vBB寄存器與vCC寄存器進行運算,結果保存到vAA寄存器。
•“binop/2addr vA, vB”:將vA寄存器與vB寄存器進行運算,結果保存到vA寄存器。
•“binop/lit16 vA, vB, #+CCCC”:將vB寄存器與常量 CCCC進行運算,結果保存到vA寄存器。
•“binop/lit8 vAA, vBB, #+CC”:將vBB寄存器與常量CC進行運算,結果保存到vAA寄存器。
后面3類指令比第1類指令分別多出了2addr,lit16,lit8等指令后綴。四類指令中基礎字節碼相同的指令執行的運算操作是類似的,第1類指令中,根據數據的類型不同會在基礎字節碼后面加上數據類型后綴,如 -int 或 -long 分別表示操作的數據類型為整型與長整型。第1類指令可歸類如下:
•“add-type”:vBB寄存器與vCC寄存器值進行加法運算(vBB + vCC)
•”sub-type”:vBB寄存器與vCC寄存器值進行減法運算(vBB - vCC)
•”mul-type”:vBB寄存器與vCC寄存器值進行乘法運算(vBB * vCC)
•”div-type”:vBB寄存器與vCC寄存器值進行除法運算(vBB / vCC)
•”rem-type”:vBB寄存器與vCC寄存器值進行模運算(vBB % vCC)
•”and-type”:vBB寄存器與vCC寄存器值進行與運算(vBB & vCC)
•”or-type”:vBB寄存器與vCC寄存器值進行或運算(vBB | vCC)
•”xor-type”:vBB寄存器與vCC寄存器值進行異或運算(vBB ^ vCC)
•”shl-type”:vBB寄存器值(有符號數)左移vCC位(vBB << vCC )
•”shr-type”:vBB寄存器值(有符號)右移vCC位(vBB >> vCC)
•”ushr-type”:vBB寄存器值(無符號數)右移vCC位(vBB >>> vCC)
其中基礎字節碼后面的-type可以是-int,-long, -float,-double。后面3類指令與之類似。
9.方法調用指令
方法調用指令負責調用類實例的方法。它的基礎指令為 invoke,方法調用指令有“invoke-kind {vC, vD, vE, vF, vG},meth@BBBB”與“invoke-kind/range {vCCCC .. vNNNN},meth@BBBB”兩類,兩類指令在作用上並無不同,只是后者在設置參數寄存器時使用了range來指定寄存器的范圍。根據方法類型的不同,共有如下五條方法調用指令:
•invoke-virtual或 invoke-virtual/range調用實例的虛方法。
•invoke-super或”invoke-super/range調用實例的父類方法。
•invoke-direct或“invoke-direct/range調用實例的直接方法。
•invoke-static或invoke-static/range調用實例的靜態方法。
•invoke-interface或invoke-interface/range調用實例的接口方法。
•invoke-virtual或 invoke-virtual/range調用實例的虛方法。
•invoke-super或”invoke-super/range調用實例的父類方法。
•invoke-direct或“invoke-direct/range調用實例的直接方法。
•invoke-static或invoke-static/range調用實例的靜態方法。
•invoke-interface或invoke-interface/range調用實例的接口方法。
在Android4.0系統中,Dalvik指令集中增加了“invoke-kind/jumbo {vCCCC .. vNNNN},meth@BBBBBBBB”這類指令,它與上面介紹的兩類指令作用相同,只是在指令中增加了jumbo字節碼后綴,且寄存器值與指令的索引取值范圍更大。
方法調用指令的返回值必須使用move-result*指令來獲取。如下面兩條指令:
invoke-static {}, Landroid/os/Parcel;->obtain() Landroid/os/Parcel;
move-result-object v012
move-result-object v012
10.異常處理指令
Dalvik指令集中有一條指令用來拋出異常。
•throw vAA:拋出vAA寄存器中指定類型的異常。
11.實例操作指令
與實例相關的操作包括實例的類型轉換,檢查及新建等:
•check-cast vAA, type@BBBB:將vAA寄存器中的對象引用轉換成指定的類型,如果失敗會拋出ClassCastException異常。如果類型B指定的是基本類型,對於非基本類型的A來說,運行時始終會失敗。
•instance-of vA, vB, type@CCCC:判斷vB寄存器中的對象引用是否可以轉換成指定的類型,如果可以vA寄存器賦值為1,否則vA寄存器賦值為0。
•new-instance vAA, type@BBBB:構造一個指定類型對象的新實例,並將對象引用賦值給vAA寄存器,類型符type指定的類型不能是數組類。
•check-cast/jumbo vAAAA, type@BBBBBBBB:指令功能與“check-cast vAA, type@BBBB”相同,只是寄存器值與指令的索引取值范圍更大(Android4.0中新增的指令)。
•instance-of/jumbo vAAAA, vBBBB, type@CCCCCCCC:指令功能與“instance-of vA, vB, type@CCCC”相同,只是寄存器值與指令的索引取值范圍更大(Android4.0中新增的指令)。
•new-instance/jumbo vAAAA, type@BBBBBBBB:指令功能與“new-instance vAA, type@BBBB”相同,只是寄存器值與指令的索引取值范圍更大(Android4.0中新增的指令)。
12.返回指令
返回指令指的是函數結尾時運行的最后一條指令。它的基礎字節碼為teturn,共有以下四條返回指令:
•return-void:表示函數從一個void方法返回。
•return vAA:表示函數返回一個32位非對象類型的值,返回值寄存器為8位的寄存器vAA。
•return-wide vAA:表示函數返回一個64位非對象類型的值,返回值為8位的寄存器對vAA。
•return-object vAA:表示函數返回一個對象類型的值。返回值為8位的寄存器vAA。
•return vAA:表示函數返回一個32位非對象類型的值,返回值寄存器為8位的寄存器vAA。
•return-wide vAA:表示函數返回一個64位非對象類型的值,返回值為8位的寄存器對vAA。
•return-object vAA:表示函數返回一個對象類型的值。返回值為8位的寄存器vAA。
13.數據操作指令
數據操作指令為move。move指令的原型為“move destination,source”,move指令根據字節碼的大小與類型不同,后面會跟上不同的后綴。
•move vA, vB:將vB寄存器的值賦給vA寄存器,A源寄存器與目的寄存器都為4位。
•move/from16 vAA, vBBBB:將vBBBB寄存器的值賦給vAA寄存器,源寄存器為16位,目的寄存器為8位。
•move/16 vAAAA, vBBBB:將vBBBB寄存器的值賦給vAAAA寄存器,源寄存器與目的寄存器都為16位。
•move-wide vA, vB:為4位的寄存器對賦值。源寄存器與目的寄存器都為4位。
•move-wide/from16 vAA, vBBBB 與“move-wide/16 vAAAA, vBBBB”實現與“move-wide”相同。
•move-object vA, vB:為對象賦值。源寄存器與目的寄存器都為4位。
•move-object/from16 vAA, vBBBB:為對象賦值。源寄存器為16位,目的寄存器為8位。
•move-object/16 vAA, vBBBB:為對象賦值。源寄存器與目的寄存器都為16位。
•move-result vAA:將上一個invoke類型指令操作的單字非對象結果賦給vAA寄存器。
•move-result-wide vAA:將上一個invoke類型指令操作的雙字非對象結果賦給vAA寄存器。
•move-result-object vAA:將上一個invoke類型指令操作的對象結果賦給vAA寄存器。
•move-exception vAA:保存一個運行時發生的異常到vAA寄存器,這條指令必須是異常發生時的異常處理器的一條指令。否則的話,指令無效。
•move/from16 vAA, vBBBB:將vBBBB寄存器的值賦給vAA寄存器,源寄存器為16位,目的寄存器為8位。
•move/16 vAAAA, vBBBB:將vBBBB寄存器的值賦給vAAAA寄存器,源寄存器與目的寄存器都為16位。
•move-wide vA, vB:為4位的寄存器對賦值。源寄存器與目的寄存器都為4位。
•move-wide/from16 vAA, vBBBB 與“move-wide/16 vAAAA, vBBBB”實現與“move-wide”相同。
•move-object vA, vB:為對象賦值。源寄存器與目的寄存器都為4位。
•move-object/from16 vAA, vBBBB:為對象賦值。源寄存器為16位,目的寄存器為8位。
•move-object/16 vAA, vBBBB:為對象賦值。源寄存器與目的寄存器都為16位。
•move-result vAA:將上一個invoke類型指令操作的單字非對象結果賦給vAA寄存器。
•move-result-wide vAA:將上一個invoke類型指令操作的雙字非對象結果賦給vAA寄存器。
•move-result-object vAA:將上一個invoke類型指令操作的對象結果賦給vAA寄存器。
•move-exception vAA:保存一個運行時發生的異常到vAA寄存器,這條指令必須是異常發生時的異常處理器的一條指令。否則的話,指令無效。
14.對象操作指令
與對象實例相關的操作,比如對象創建,對象檢查等.
15.數組操作指令
數組操作包括獲取數組長度,新建數組,數組賦值,數組元素取值與賦值等操作。
•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)的數組並填充數組內容。vA寄存器是隱含使用的,除了指定數組的大小外還指定了參數的個數,vC~vG是使用到的參數寄存序列。
•filled-new-array/range {vCCCC ..vNNNN}, type@BBBB:指令功能與“filled-new-array {vC, vD, vE, vF, vG},type@BBBB”相同,只是參數寄存器使用range字節碼后綴指定了取值范圍 ,vC是第一個參數寄存器,N = A +C -1。
•fill-array-data vAA, +BBBBBBBB:用指定的數據來填充數組,vAA寄存器為數組引用,引用必須為基礎類型的數組,在指令后面會緊跟一個數據表。
•new-array/jumbo vAAAA, vBBBB,type@CCCCCCCC:指令功能與“new-
array vA,vB,type@CCCC”相同,只是寄存器值與指令的索引取值范圍更大(Android4.0中新增的指令)。
•filled-new-array/jumbo {vCCCC ..vNNNN},type@BBBBBBBB:指令功能與“filled-new-array/range {vCCCC ..vNNNN},type@BBBB”相同,只是索引取值范圍更大(Android4.0中新增的指令)。
•arrayop vAA, vBB, vCC:對vBB寄存器指定的數組元素進入取值與賦值。vCC寄存器指定數組元素索引,vAA寄存器用來存放讀取的或需要設置的數組元素的值。讀取元素使用aget類指令,元素賦值使用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。
————————————————
版權聲明:本文為CSDN博主「逆風Lee」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/lixpjita39/article/details/75193833
————————————————
版權聲明:本文為CSDN博主「逆風Lee」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/lixpjita39/article/details/75193833