Android Dalvik虛擬機實戰

簡介

Android 平臺雖然是使用java語言來開發應用程序,但Android程序卻不是運行在標準java虛擬機上的。谷歌專門爲Android平臺設計了一套虛擬機來運行Android程序。它就是Dalvik虛擬機。特點

  • 體積小,佔用內存空間小。
  • 專有的DEX可執行文件格式,體積更小,執行速度更快。
  • 常量池採用32位索引值,尋址類方法名、字段名、常量更快。
  • 基於寄存器架構,並擁有一套完整的指令系統。
  • 提供了對象生命週期管理、堆棧管理、線程管理、安全和異常管理以及垃圾回收等重要功能。
  • 所有的Android程序都運行在Android系統進程裏,每個進程對應着一個Dalvik虛擬機實例。

Dalvik虛擬機與Java虛擬機的區別

1、Java虛擬機運行的是java字節碼,Dalvik虛擬機運行的是Dalvik字節碼。
2、Dalvik 可執行文件體積更小。
3、Java虛擬機與Dalvik虛擬機架構不同。Dalvik 彙編語言
1、Dalvik指令
指令大多由三個字符組成,前兩個是數字,最後一個是字母。
第一個數字是表示指令有多少個16位的字組成。
第二個數字是表示指令最多使用寄存器的個數。特殊標記‘r’標識使用一定範圍內的寄存器。
第三個字母爲類型嗎,表示指令用到的額外的數據的類型。
例如:22x
第一個2表示 指令有兩個16位字組成
第二個2表示 指令使用到2個寄存器
第三個x表示沒有使用到額外的數據
2、DEX文件反彙編工具
目前DEX可執行文件主流的反彙編工具有BakSmali與Dedexer。
指令如:

java -jar baksmali.jar -o baksmaliout hello.dex  
java -jar ddx.jar -d ddxout hello.dex 

3、Dalvik 寄存器
Dalvik虛擬機是作用於特定架構的CPU上運行的,在設計之初採用了ARM架構,ARM架構的CPU本身繼承了多個寄存器,Dalvik將部分寄存器映射到了ARM寄存器上,還有一個部分則通過調用棧進行模擬。.

Dalvik虛擬機又是如何虛擬地使用寄存器的呢?Dalvik虛擬機爲每個進程維護一個調用棧,這個調用棧其中一個作用就是用來‘虛擬’寄存器。

4、兩種不同的寄存器表示方法
v 命名法採用以小寫字母 ‘v’開頭的方式表示函數中用到的局部變量與參數,所有的寄存器命名從v0開始,依次遞增。
p 命名法對函數的局部變量寄存器命名沒有影響,它的命名規則:函數中引入的參數命名從p0開始,依次遞增。Dalvik字節碼的類型、方法與字段
1、類型
Dalvik字節碼只有兩種類型,基本類型與引用類型。
2、方法
Dalvik使用方法名、類型參數與返回值來詳情描述一個方法。
方法格式如下: Lpackage/name/ObjectName;->MethodName(III)Z
3、字段
Dalvik虛擬機定位字段與字節碼靜態分析時會用到它。
格式如下:Lpackage/name/ObjectName;->FieldName:Ljava/lang/String;Dalvik指令集
1、空操作指令的助記符爲nop。它的值爲00,通常nop指令被用來作對齊代碼只用。
2、數據操作指令爲move。move 指令根據字節碼的大小與類型不同,後面會跟上不同的後綴。
3、返回指令指的是函數結尾時運行的最後一條指令。return-void、return vAA、return-wide vAA、return-object vAA
4、數據定義指令用來定義程序中用到的常量、字符串、類等數據。它的基礎字節碼爲const。如:const/4 vA,#+B
5、鎖指令多用在多線程程序中對同一對象的操作。如:
monitor-enter vAA 鎖住
monitor-exit vAA 釋放
6、實例操作指令包括實例的類型轉換、檢查以及新建等。
7、數組操作指令包括獲取數組長度、新建數組、數組賦值、數組元素取值與賦值等操作。
8、異常指令集中有一條指令用來拋出異常。如:throw vAA
9、跳轉指令用於從當前地址跳轉到指定的偏移處。如:goto、switch、if
10、比較指令用於對兩個寄存器的值進行比較。如:cmpkind vAA,vBB
11、字段操作指令用來對對象實例的字段進行讀寫操作。如:iinstanceop vA,vB,field@CCCC 與sstaticop vAA,field@BBBB
12、方法調用指令負責調用類實例的方法。它的基礎指令爲invoke。如:invoke-kind/range {vCCCC…vNNNNN}
13、數據轉換指令用於將一種類型的數值轉換成另一種類型。如:unop vA,vB
14、數據運算指令包括算術運算指令與邏輯運算指令。如:binop vAA,vBB,vCC 、add-type、sub-type……。Dalvik指令練習
寫一個Dalvik版的Hello World。
1、編寫smali文件


.class public LHelloWorld;
.super Ljava/lang/Object;
.method public static main([Ljava/lang/String;)V
    .registers 4
	.parameter
    .prologue
	#空指令
    nop
    nop
    nop
    nop
	#數據定義指令
	const/16 v0, 0x8
	const/4 v1, 0x5
	const/4 v2, 0x3
	#數據操作指令
	move v1, v2
	#數組操作指令
	new-array v0, v0, [I
	array-length v1, v0
	#實例操作指令
	new-instance v1, Ljava/lang/StringBuilder;
	#方法調用指令
	invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V
	#跳轉指令
	if-nez v0, :cond_0
	goto :goto_0
	:cond_0
	#數據轉換指令
	int-to-float v2, v2
	#數據運算指令
	add-float v2, v2, v2
	#比較指令
	cmpl-float v0, v2, v2
	#字段操作指令
	sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
	const-string v1, "Hello World" #構造字符串
	#方法調用指令
	invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
	#返回指令
	:goto_0
    return-void
.end method

2、編譯smali文件

java -jar smali.jar -o classes.dex HelloWorld.smali  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章