柚子快報激活碼778899分享:Smali 簡介與JVM指令
柚子快報激活碼778899分享:Smali 簡介與JVM指令
目錄
Smali 簡介
Smali文件結(jié)構(gòu)
基本類型
對象
數(shù)組
方法聲明及調(diào)用
寄存器聲明及使用
Dalvik指令集
JVM
將常量壓入棧的指令
從棧中的局部變量中裝載值的指令
將棧中的值存入局部變量的指令
通用(無類型)棧操作
類型轉(zhuǎn)換
整數(shù)運算
邏輯運算
移位操作
按位布爾運算
浮點運算
對象和數(shù)組
對象操作指令
數(shù)組操作指令
控制流
條件分支指令
比較指令
無條件轉(zhuǎn)移指令
表跳轉(zhuǎn)指令
異常
方法調(diào)用與返回
方法調(diào)用指令
方法返回指令
線程同步
總結(jié)
Smali 簡介
Smali是用于Dalvik(Android虛擬機)的反匯編程序?qū)崿F(xiàn),匯編工具(將Smali代碼匯編為dex文件)為smali.jar,與之對應(yīng)的baksmali.jar則是反匯編程序(下載地址)。
Smali支持注解、調(diào)試信息、行數(shù)信息等基本Java的基本特性,可以說是很接近Java編譯在JVM上的中間語言了,一般用來做Android程序的逆向工程。
Smali是用于做反匯編的一種語言實現(xiàn),如果可以,自己也能定義一套這樣的語言,實現(xiàn)反匯編的效果
Smali文件結(jié)構(gòu)
一個Smali文件對應(yīng)的是一個Java的類,更準(zhǔn)確的說是一個.class文件,如果有內(nèi)部類,需要寫成ClassName$InnerClassA、ClassName$InnerClassB…這樣的形式
基本類型
類型關(guān)鍵字 對應(yīng)Java中的類型說明 V void,只能用于返回類型 Z boolean B byte S short C char I int J long (64 bits) F float D double (64 bits)
對象
Object類型,即引用類型的對象,在引用時,使用L開頭,后面緊接著的是完整的包名,比如:java.lang.String對應(yīng)的Smali語法則是Ljava/lang/String
數(shù)組
數(shù)組定義比較有意思,一維數(shù)組在類型的左邊加一個方括號,比如:[I等同于Java的int[],每多一維就加一個方括號,最多可以設(shè)置255維。
方法聲明及調(diào)用
官方Wiki中給出的Smali引用方法的模板如下: Lpackage/name/ObjectName;->MethodName(III)Z 第一部分Lpackage/name/ObjectName;用于聲明具體的類型,以便JVM尋找
第二部分MethodName(III)Z,其中MethodName為具體的方法名,()中的字符,表示了參數(shù)數(shù)量和類型,即3個int型參數(shù),Z為返回值的類型,即返回Boolean類型
由于方法的參數(shù)列表沒有使用逗號這樣的分隔符進行劃分,所以只能從左到右,根據(jù)類型定義來區(qū)分參數(shù)個數(shù),這一點需要比較仔細來觀察
如果需要調(diào)用構(gòu)造方法,則MethodName為:
寄存器聲明及使用
在Smali中,如果需要存儲變量,必須先聲明足夠數(shù)量的寄存器,1個寄存器可以存儲32位長度的類型,比如Int,而兩個寄存器可以存儲64位長度類型的數(shù)據(jù),比如Long或Double
聲明可使用的寄存器數(shù)量的方式為:.registers N,N代表需要的寄存器的總個數(shù),同時,還有一個關(guān)鍵字.locals,它用于聲明非參數(shù)的寄存器個數(shù)(包含在registers聲明的個數(shù)當(dāng)中),也叫做本地寄存器,只在一個方法內(nèi)有效,但不常用,一般使用registers即可
示例:
.method private test(I)V
.registers 4 # 聲明總共需要使用4個寄存器
const-string v0, "LOG" # 將v0寄存器賦值為字符串常量"LOG"
move v1, p1 # 將int型參數(shù)的值賦給v1寄存器
return-void
.end method
結(jié)合Dalvik常用的指令進行操作,即可實現(xiàn)一些需要的功能
那么,如何確定需要使用的寄存器的個數(shù)?
由于非static方法,需要占用一個寄存器以保存this指針,那么這類方法的寄存器個數(shù),最低就為1,如果還需要處理傳入的參數(shù),則需要再次疊加,此時還需要考慮Double和Float這種需要占用兩個寄存器的參數(shù)類型,舉例來看:
如果一個Java方法聲明如下: myMethod(int p1, float p2, boolean p3)
那么對應(yīng)的Smali則為: method LMyObject;->myMethod(IJZ)V 此時,寄存器的對應(yīng)情況如下:
寄存器名稱 對應(yīng)的引用 p0 this p1 int型的p1參數(shù) p2, p3 float型的p2參數(shù) p4 boolean型的p3參數(shù)
那么最少需要的寄存器個數(shù)則為:5
如果方法體內(nèi)含有常量、變量等定義,則需要根據(jù)情況增加寄存器個數(shù),數(shù)量只要滿足需求,保證需要獲取的值不被后面的賦值沖掉即可,方法有:存入類中的字段中(存入后,寄存器可被重新賦值),或者長期占用一個寄存器
Dalvik指令集
如果需要使用Smali編寫程序,還需要掌握常用的Dalvik虛擬機指令,其合集稱為Dalvik指令集。這些指令有點類似x86匯編的指令,但指令更多,使用也非常簡單方便。
一般的指令格式為:[op]-[type](可選)/[位寬,默認4位] [目標(biāo)寄存器],[源寄存器](可選),比如:move v1,v2,move-wide/from16 v1,v2
這里也列舉一些常用的指令,并結(jié)合Smali進行說明:
移位操作: 此類操作常用于賦值
指令 說明 move v1,v2 將v2中的值移入到v1寄存器中(4位,支持int型) move/from16 v1,v2 將16位的v2寄存器中的值移入到8位的v1寄存器中 move/16 v1,v2 將16位的v2寄存器中的值移入到16位的v1寄存器中 move-wide v1,v2 將寄存器對(一組,用于支持雙字型)v2中的值移入到v1寄存器對中(4位,猜測支持float、double型) move-wide/from16 v1,v2 將16位的v2寄存器對(一組)中的值移入到8位的v1寄存器中 move-wide/16 v1,v2 將16位的v2寄存器對(一組)中的值移入到16位的v1寄存器中 move-object v1,v2 將v2中的對象指針移入到v1寄存器中 move-object/from16 v1,v2 將16位的v2寄存器中的對象指針移入到v1(8位)寄存器中 move-object/16 v1,v2 將16位的v2寄存器中的對象指針移入到v1(16位)寄存器中 move-result v1 將這個指令的上一條指令計算結(jié)果,移入到v1寄存器中(需要配合invoke-static、invoke-virtual等指令使用) move-result-object v1 將上條計算結(jié)果的對象指針移入v1寄存器 move-result-wide v1 將上條計算結(jié)果(雙字)的對象指針移入v1寄存器 move-exception v1 將異常移入v1寄存器,用于捕獲try-catch語句中的異常
返回操作:
用于返回值,對應(yīng)Java中的return語句
指令 說明 return-void 返回void,即直接返回 return v1 返回v1寄存器中的值 return-object v1 返回v1寄存器中的對象指針 return-wide v1 返回雙字型結(jié)果給v1寄存器
常量操作:
用于聲明常量,比如字符串常量(僅聲明,String a = "abc"這種語句包含聲明和賦值)
指令 說明 const(/4、/16、/hight16) v1 xxx 將常量xxx賦值給v1寄存器,/后的類型,需要根據(jù)xxx的長度選擇 const-wide(/16、/32、/hight16) v1 xxx 將雙字型常量xxx賦值給v1寄存器,/后的類型,需要根據(jù)xxx的長度選擇 const-string(/jumbo) v1 “aaa” 將字符串常量”aaa”賦給v1寄存器,過長時需要加上jumbo const-class v1 La/b/TargetClass 將Class常量a.b.TargetClass賦值給v1,等價于a.b.TargetClass.class
調(diào)用操作:
用于調(diào)用方法,基本格式:invoke-kind {vC, vD, vE, vF, vG}, meth@BBBB,其中,BBBB代表方法引用(參見上面介紹的方法定義及調(diào)用),vC~G為需要的參數(shù),根據(jù)順序一一對應(yīng)
指令 說明 invoke-virtual 用于調(diào)用一般的,非private、非static、非final、非構(gòu)造函數(shù)的方法,它的第一個參數(shù)往往會傳p0,也就是this指針 invoke-super 用于調(diào)用父類中的方法,其他和invoke-virtual保持一致 invoke-direct 用于調(diào)用private修飾的方法,或者構(gòu)造方法 invoke-static 用于調(diào)用靜態(tài)方法,比如一些工具類 invoke-interface 用于調(diào)用interface中的方法
判斷操作:
判斷操作用來比較一個寄存器中的值,是否與目標(biāo)寄存器中的值相等或不等,對應(yīng)Java中的if語句,格式為:if-[test] v1,v2, [condition],其衍生操作還有專門與0進行比較的if-[test]z v1, [condition],其中[condition]為符合判斷結(jié)果后的跳轉(zhuǎn)條件,需要提前定義好。判斷操作也通常和goto配合使用,用來實現(xiàn)循環(huán)或者if-else語句
指令 說明 if-eq v1,v2 判斷兩個寄存器中的值是否相等 if-ne v1,v2 判斷兩個寄存器中的值是否不相等 if-lt v1,v2 判斷v1寄存器中的值是否小于v2寄存器中的值(lt == less than) if-ge v1,v2 判斷v1寄存器中的值是否大于或等于v2寄存器中的值(ge == great than or equals) if-gt v1,v2 判斷v1寄存器中的值是否大于v2寄存器中的值(gt == great than) if-le v1,v2 判斷v1寄存器中的值是否小于或等于v2寄存器中的值(le == less than or equals)
需要注意的是,在Java中編寫的if語句,往往在對應(yīng)的Smali中,會變成相反的判斷邏輯,如下面所示:
private void test() {
int a = 0;
int b = 1;
String result;
if (a > b) {
result = "a great than b";
} else {
result = "a less than or equals b";
}
}
上面的Java代碼邏輯很簡單——一個很簡單的if語句,為了在Smali中看的更清楚,我只做了字符串賦值操作。下面是對應(yīng)的Smali代碼:
.method private test()V
.registers 4
.line 24
const/4 v0, 0x0
.line 25
.local v0, "a":I
const/4 v1, 0x1
.line 27
.local v1, "b":I
if-le v0, v1, :cond_7
.line 28
const-string v2, "a great than b"
.line 28
.local v2, "result":Ljava/lang/String;
goto :goto_9
.line 30
.end local v2 # "result":Ljava/lang/String;
:cond_7
const-string v2, "a less than or equals b"
.line 32
.restart local v2 # "result":Ljava/lang/String;
:goto_9
return-void
.end method
屬性操作:
屬性操作的分為:取值(get)和賦值(put)
目標(biāo)類型分為:數(shù)組(array)、實例(instance)和靜態(tài)(static)三種,對應(yīng)的縮寫前綴就是a、i、s
長度類型分為:默認(什么都不寫)、wide(寬,64位)、object(對象)、boolean、byte、char、short(后面幾種就不解釋了,和Java一致)
指令格式:[指令名] [源寄存器], [目標(biāo)字段所在對象寄存器], [字段指針],示例代碼如下,操作是為int型的類成員變量mIntA賦值為100:
const/16 v0, 0x64
iput v0, p0, Lcom/coderyuan/smali/MainActivity;->mIntA:I
下面列出用于實例字段的指令,其中i都可以換成a或者s,分別用于操作數(shù)組字段或者靜態(tài)字段
指令 說明 iget 取值,用于操作int這種的值類型 iget-wide 取值,用于操作wide型字段 iget-object 取值,用于操作對象引用 iget-boolean 取值,用于操作布爾類型 iget-byte 取值,用于操作字節(jié)類型 iget-char 取值,用于操作字符類型 iget-short 取值,用于操作short類型 iput 賦值,用于操作int這種的值類型 iput-wide 賦值,用于操作wide型字段 iput-object 賦值,用于操作對象引用 iput-boolean 賦值,用于操作布爾類型 iput-byte 賦值,用于操作字節(jié)類型 iput-char 賦值,用于操作字符類型 iput-short 賦值,用于操作short類型
舉例:
以下Java代碼是進行的是最基本的類成員變量的賦值、取值操作
private String mStringA;
private int mIntA;
private Activity mActivityA;
public void fieldTest() {
mStringA = "Put String to mStringA";
mIntA = 100;
mActivityA = this;
int len = mStringA.length();
}
對應(yīng)的Smali代碼如下:
# instance fields
.field private mActivityA:Landroid/app/Activity;
.field private mIntA:I
.field private mStringA:Ljava/lang/String;
# virtual methods
.method public fieldTest()V
.registers 2
.line 55
const-string v0, "Put String to mStringA"
iput-object v0, p0, Lcom/coderyuan/smali/MainActivity;->mStringA:Ljava/lang/String;
.line 56
const/16 v0, 0x64
iput v0, p0, Lcom/coderyuan/smali/MainActivity;->mIntA:I
.line 57
iput-object p0, p0, Lcom/coderyuan/smali/MainActivity;->mActivityA:Landroid/app/Activity;
.line 59
iget-object v0, p0, Lcom/coderyuan/smali/MainActivity;->mStringA:Ljava/lang/String;
invoke-virtual {v0}, Ljava/lang/String;->length()I
move-result v0
.line 60
.local v0, "len":I
return-void
.end method
根據(jù)Java和Smali代碼的對比,值得注意的是,Smali獲取類成員變量的方法,比較接近函數(shù)調(diào)用,只不過沒有函數(shù)調(diào)用時的參數(shù)
其他指令:
除以上介紹的幾種基本的Dalvik指令外,Dalvik還支持值類型轉(zhuǎn)換(如:int轉(zhuǎn)float,double轉(zhuǎn)float等)、基本運算(數(shù)學(xué)運算、邏輯運算、自增)兩種指令集
指令 說明 add-int/lit8 v1, v2, 0x1 給v2寄存器+1,并存入v1寄存器(注意:lit8是對要加的常量的長度限制,如果不寫,則為4位,還可選擇lit16,即16位) add-int/2addr v1, v2 將v1、v2寄存器中的值相加,并賦值給v1寄存器 float-to-int v1, v2 將v2寄存器中的float類型值轉(zhuǎn)換為int類型,并賦值給v1寄存器
JVM
將常量壓入棧的指令
aconst_null 將null對象引用壓入棧
iconst_m1 將int類型常量-1壓入棧
iconst_0 將int類型常量0壓入棧
iconst_1 將int類型常量1壓入操作數(shù)棧
iconst_2 將int類型常量2壓入棧
iconst_3 將int類型常量3壓入棧
iconst_4 將int類型常量4壓入棧
iconst_5 將int類型常量5壓入棧
lconst_0 將long類型常量0壓入棧
lconst_1 將long類型常量1壓入棧
fconst_0 將float類型常量0壓入棧
fconst_1 將float類型常量1壓入棧
dconst_0 將double類型常量0壓入棧
dconst_1 將double類型常量1壓入棧
bipush 將一個8位帶符號整數(shù)壓入棧
sipush 將16位帶符號整數(shù)壓入棧
ldc 把常量池中的項壓入棧
ldc_w 把常量池中的項壓入棧(使用寬索引)
ldc2_w 把常量池中l(wèi)ong類型或者double類型的項壓入棧(使用寬索引)
從棧中的局部變量中裝載值的指令
iload 從局部變量中裝載int類型值
lload 從局部變量中裝載long類型值
fload 從局部變量中裝載float類型值
dload 從局部變量中裝載double類型值
aload 從局部變量中裝載引用類型值(refernce)
iload_0 從局部變量0中裝載int類型值
iload_1 從局部變量1中裝載int類型值
iload_2 從局部變量2中裝載int類型值
iload_3 從局部變量3中裝載int類型值
lload_0 從局部變量0中裝載long類型值
lload_1 從局部變量1中裝載long類型值
lload_2 從局部變量2中裝載long類型值
lload_3 從局部變量3中裝載long類型值
fload_0 從局部變量0中裝載float類型值
fload_1 從局部變量1中裝載float類型值
fload_2 從局部變量2中裝載float類型值
fload_3 從局部變量3中裝載float類型值
dload_0 從局部變量0中裝載double類型值
dload_1 從局部變量1中裝載double類型值
dload_2 從局部變量2中裝載double類型值
dload_3 從局部變量3中裝載double類型值
aload_0 從局部變量0中裝載引用類型值
aload_1 從局部變量1中裝載引用類型值
aload_2 從局部變量2中裝載引用類型值
aload_3 從局部變量3中裝載引用類型值
iaload 從數(shù)組中裝載int類型值
laload 從數(shù)組中裝載long類型值
faload 從數(shù)組中裝載float類型值
daload 從數(shù)組中裝載double類型值
aaload 從數(shù)組中裝載引用類型值
baload 從數(shù)組中裝載byte類型或boolean類型值
caload 從數(shù)組中裝載char類型值
saload 從數(shù)組中裝載short類型值
將棧中的值存入局部變量的指令
istore 將int類型值存入局部變量
lstore 將long類型值存入局部變量
fstore 將float類型值存入局部變量
dstore 將double類型值存入局部變量
astore 將將引用類型或returnAddress類型值存入局部變量
istore_0 將int類型值存入局部變量0
istore_1 將int類型值存入局部變量1
istore_2 將int類型值存入局部變量2
istore_3 將int類型值存入局部變量3
lstore_0 將long類型值存入局部變量0
lstore_1 將long類型值存入局部變量1
lstore_2 將long類型值存入局部變量2
lstore_3 將long類型值存入局部變量3
fstore_0 將float類型值存入局部變量0
fstore_1 將float類型值存入局部變量1
fstore_2 將float類型值存入局部變量2
fstore_3 將float類型值存入局部變量3
dstore_0 將double類型值存入局部變量0
dstore_1 將double類型值存入局部變量1
dstore_2 將double類型值存入局部變量2
dstore_3 將double類型值存入局部變量3
astore_0 將引用類型或returnAddress類型值存入局部變量0
astore_1 將引用類型或returnAddress類型值存入局部變量1
astore_2 將引用類型或returnAddress類型值存入局部變量2
astore_3 將引用類型或returnAddress類型值存入局部變量3
iastore 將int類型值存入數(shù)組中
lastore 將long類型值存入數(shù)組中
fastore 將float類型值存入數(shù)組中
dastore 將double類型值存入數(shù)組中
aastore 將引用類型值存入數(shù)組中
bastore 將byte類型或者boolean類型值存入數(shù)組中
castore 將char類型值存入數(shù)組中
sastore 將short類型值存入數(shù)組中
wide指令
wide 使用附加字節(jié)擴展局部變量索引
通用(無類型)棧操作
nop 不做任何操作
pop 彈出棧頂端一個字長的內(nèi)容
pop2 彈出棧頂端兩個字長的內(nèi)容
dup 復(fù)制棧頂部一個字長內(nèi)容
dup_x1 復(fù)制棧頂部一個字長的內(nèi)容,然后將復(fù)制內(nèi)容及原來彈出的兩個字長的內(nèi)容壓入棧
dup_x2 復(fù)制棧頂部一個字長的內(nèi)容,然后將復(fù)制內(nèi)容及原來彈出的三個字長的內(nèi)容壓入棧
dup2 復(fù)制棧頂部兩個字長內(nèi)容
dup2_x1 復(fù)制棧頂部兩個字長的內(nèi)容,然后將復(fù)制內(nèi)容及原來彈出的三個字長的內(nèi)容壓入棧
dup2_x2 復(fù)制棧頂部兩個字長的內(nèi)容,然后將復(fù)制內(nèi)容及原來彈出的四個字長的內(nèi)容壓入棧
swap 交換棧頂部兩個字長內(nèi)容
類型轉(zhuǎn)換
i2l 把int類型的數(shù)據(jù)轉(zhuǎn)化為long類型
i2f 把int類型的數(shù)據(jù)轉(zhuǎn)化為float類型
i2d 把int類型的數(shù)據(jù)轉(zhuǎn)化為double類型
l2i 把long類型的數(shù)據(jù)轉(zhuǎn)化為int類型
l2f 把long類型的數(shù)據(jù)轉(zhuǎn)化為float類型
l2d 把long類型的數(shù)據(jù)轉(zhuǎn)化為double類型
f2i 把float類型的數(shù)據(jù)轉(zhuǎn)化為int類型
f2l 把float類型的數(shù)據(jù)轉(zhuǎn)化為long類型
f2d 把float類型的數(shù)據(jù)轉(zhuǎn)化為double類型
d2i 把double類型的數(shù)據(jù)轉(zhuǎn)化為int類型
d2l 把double類型的數(shù)據(jù)轉(zhuǎn)化為long類型
d2f 把double類型的數(shù)據(jù)轉(zhuǎn)化為float類型
i2b 把int類型的數(shù)據(jù)轉(zhuǎn)化為byte類型
i2c 把int類型的數(shù)據(jù)轉(zhuǎn)化為char類型
i2s 把int類型的數(shù)據(jù)轉(zhuǎn)化為short類型
整數(shù)運算
iadd 執(zhí)行int類型的加法
ladd 執(zhí)行l(wèi)ong類型的加法
isub 執(zhí)行int類型的減法
lsub 執(zhí)行l(wèi)ong類型的減法
imul 執(zhí)行int類型的乘法
lmul 執(zhí)行l(wèi)ong類型的乘法
idiv 執(zhí)行int類型的除法
ldiv 執(zhí)行l(wèi)ong類型的除法
irem 計算int類型除法的余數(shù)
lrem 計算long類型除法的余數(shù)
ineg 對一個int類型值進行取反操作
lneg 對一個long類型值進行取反操作
iinc 把一個常量值加到一個int類型的局部變量上
邏輯運算
移位操作
ishl 執(zhí)行int類型的向左移位操作
lshl 執(zhí)行l(wèi)ong類型的向左移位操作
ishr 執(zhí)行int類型的向右移位操作
lshr 執(zhí)行l(wèi)ong類型的向右移位操作
iushr 執(zhí)行int類型的向右邏輯移位操作
lushr 執(zhí)行l(wèi)ong類型的向右邏輯移位操作
按位布爾運算
iand 對int類型值進行“邏輯與”操作
land 對long類型值進行“邏輯與”操作
ior 對int類型值進行“邏輯或”操作
lor 對long類型值進行“邏輯或”操作
ixor 對int類型值進行“邏輯異或”操作
lxor 對long類型值進行“邏輯異或”操作
浮點運算
fadd 執(zhí)行float類型的加法
dadd 執(zhí)行double類型的加法
fsub 執(zhí)行float類型的減法
dsub 執(zhí)行double類型的減法
fmul 執(zhí)行float類型的乘法
dmul 執(zhí)行double類型的乘法
fdiv 執(zhí)行float類型的除法
ddiv 執(zhí)行double類型的除法
frem 計算float類型除法的余數(shù)
drem 計算double類型除法的余數(shù)
fneg 將一個float類型的數(shù)值取反
dneg 將一個double類型的數(shù)值取反
對象和數(shù)組
對象操作指令
new 創(chuàng)建一個新對象
checkcast 確定對象為所給定的類型
getfield 從對象中獲取字段
putfield 設(shè)置對象中字段的值
getstatic 從類中獲取靜態(tài)字段
putstatic 設(shè)置類中靜態(tài)字段的值
instanceof 判斷對象是否為給定的類型
數(shù)組操作指令
newarray 分配數(shù)據(jù)成員類型為基本上數(shù)據(jù)類型的新數(shù)組
anewarray 分配數(shù)據(jù)成員類型為引用類型的新數(shù)組
arraylength 獲取數(shù)組長度
multianewarray 分配新的多維數(shù)組
控制流
條件分支指令
ifeq 如果等于0,則跳轉(zhuǎn)
ifne 如果不等于0,則跳轉(zhuǎn)
iflt 如果小于0,則跳轉(zhuǎn)
ifge 如果大于等于0,則跳轉(zhuǎn)
ifgt 如果大于0,則跳轉(zhuǎn)
ifle 如果小于等于0,則跳轉(zhuǎn)
if_icmpcq 如果兩個int值相等,則跳轉(zhuǎn)
if_icmpne 如果兩個int類型值不相等,則跳轉(zhuǎn)
if_icmplt 如果一個int類型值小于另外一個int類型值,則跳轉(zhuǎn)
if_icmpge 如果一個int類型值大于或者等于另外一個int類型值,則跳轉(zhuǎn)
if_icmpgt 如果一個int類型值大于另外一個int類型值,則跳轉(zhuǎn)
if_icmple 如果一個int類型值小于或者等于另外一個int類型值,則跳轉(zhuǎn)
ifnull 如果等于null,則跳轉(zhuǎn)
ifnonnull 如果不等于null,則跳轉(zhuǎn)
if_acmpeq 如果兩個對象引用相等,則跳轉(zhuǎn)
if_acmpnc 如果兩個對象引用不相等,則跳轉(zhuǎn)
比較指令
lcmp 比較long類型值
fcmpl 比較float類型值(當(dāng)遇到NaN時,返回-1)
fcmpg 比較float類型值(當(dāng)遇到NaN時,返回1)
dcmpl 比較double類型值(當(dāng)遇到NaN時,返回-1)
dcmpg 比較double類型值(當(dāng)遇到NaN時,返回1)
無條件轉(zhuǎn)移指令
goto 無條件跳轉(zhuǎn)
goto_w 無條件跳轉(zhuǎn)(寬索引)
表跳轉(zhuǎn)指令
tableswitch 通過索引訪問跳轉(zhuǎn)表,并跳轉(zhuǎn)
lookupswitch 通過鍵值匹配訪問跳轉(zhuǎn)表,并執(zhí)行跳轉(zhuǎn)操作
異常
athrow 拋出異?;蝈e誤
finally子句
jsr 跳轉(zhuǎn)到子例程
jsr_w 跳轉(zhuǎn)到子例程(寬索引)
rct 從子例程返回
方法調(diào)用與返回
方法調(diào)用指令
invokcvirtual 運行時按照對象的類來調(diào)用實例方法
invokespecial 根據(jù)編譯時類型來調(diào)用實例方法
invokestatic 調(diào)用類(靜態(tài))方法
invokcinterface 調(diào)用接口方法
方法返回指令
ireturn 從方法中返回int類型的數(shù)據(jù)
lreturn 從方法中返回long類型的數(shù)據(jù)
freturn 從方法中返回float類型的數(shù)據(jù)
dreturn 從方法中返回double類型的數(shù)據(jù)
areturn 從方法中返回引用類型的數(shù)據(jù)
return 從方法中返回,返回值為void
線程同步
montiorenter 進入并獲取對象監(jiān)視器
monitorexit 釋放并退出對象監(jiān)視器
總結(jié)
JVM指令助記符
變量到操作數(shù)棧:iload,iload_,lload,lload_,fload,fload_,dload,dload_,aload,aload_
操作數(shù)棧到變量:
istore,istore_,lstore,lstore_,fstore,fstore_,dstore,dstor_,astore,astore_
常數(shù)到操作數(shù)棧:
bipush,sipush,ldc,ldc_w,ldc2_w,aconst_null,iconst_ml,iconst_,lconst_,fconst_,dconst_
加:iadd,ladd,fadd,dadd
減:isub,lsub,fsub,dsub
乘:imul,lmul,fmul,dmul
除:idiv,ldiv,fdiv,ddiv
余數(shù):irem,lrem,frem,drem
取負:ineg,lneg,fneg,dneg
移位:ishl,lshr,iushr,lshl,lshr,lushr
按位或:ior,lor
按位與:iand,land
按位異或:ixor,lxor
類型轉(zhuǎn)換:i2l,i2f,i2d,l2f,l2d,f2d(放寬數(shù)值轉(zhuǎn)換)
i2b,i2c,i2s,l2i,f2i,f2l,d2i,d2l,d2f(縮窄數(shù)值轉(zhuǎn)換)
創(chuàng)建類實便:new
創(chuàng)建新數(shù)組:newarray,anewarray,multianwarray
訪問類的域和類實例域:getfield,putfield,getstatic,putstatic
把數(shù)據(jù)裝載到操作數(shù)棧:baload,caload,saload,iaload,laload,faload,daload,aaload
從操作數(shù)棧存存儲到數(shù)組:
bastore,castore,sastore,iastore,lastore,fastore,dastore,aastore
獲取數(shù)組長度:arraylength
檢相類實例或數(shù)組屬性:instanceof,checkcast
操作數(shù)棧管理:pop,pop2,dup,dup2,dup_xl,dup2_xl,dup_x2,dup2_x2,swap
有條件轉(zhuǎn)移:ifeq,iflt,ifle,ifne,ifgt,ifge,ifnull,ifnonnull,if_icmpeq,if_icmpene,
if_icmplt,if_icmpgt,if_icmple,if_icmpge,if_acmpeq,if_acmpne,lcmp,fcmpl
fcmpg,dcmpl,dcmpg
復(fù)合條件轉(zhuǎn)移:tableswitch,lookupswitch
無條件轉(zhuǎn)移:goto,goto_w,jsr,jsr_w,ret
調(diào)度對象的實便方法:invokevirtual
調(diào)用由接口實現(xiàn)的方法:invokeinterface
調(diào)用需要特殊處理的實例方法:invokespecial
調(diào)用命名類中的靜態(tài)方法:invokestatic
方法返回:ireturn,lreturn,freturn,dreturn,areturn,return
異常:athrow
finally關(guān)鍵字的實現(xiàn)使用:jsr,jsr_w,ret
柚子快報激活碼778899分享:Smali 簡介與JVM指令
推薦閱讀
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。