Smali源代码分析教程(转)
dalvik字節碼有兩種類型,原始類型和引用類型。對象和數組是引用類型,其它都是原始類型。
V??void,只能用于返回值類型
Z??boolean
B??byte
S??short
C??char
I??int
J??long(64位)
F??float
D??double(64位)
對象以Lpackage/name/ObjectName;的形式表示。前面的L表示這是一個對象類型,package/name/是該對象所在的包,ObjectName是對象的名字,“;”表示對象名稱的結束。相當于java中的package.name.ObjectName。例如:Ljava/lang/String;相當于java.lang.String
數組的表示形式
???[I——表示一個整型一維數組,相當于java中的int[]。
???對于多維數組,只要增加[就行了。[[I相當于int[][],[[[I相當于int[][][]。注意每一維的最多255個。
???對象數組的表示:[Ljava/lang/String;表示一個String對象數組。
方法
表示形式:Lpackage/name/ObjectName;->MethodName(III)Z
???Lpackage/name/ObjectName;表示類型,MethodName是方法名。III為參數(在此是3個整型參數),Z是返回類型(bool型)。
???方法的參數是一個接一個的,中間沒有隔開。
一個更復雜的例子:
method(I[[IILjava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
在java中則為:
String?method(int,?int[][],?int,?String,?Object[])
字段
表示形式:
Lpackage/name/ObjectName;->FieldName:Ljava/lang/String;
即包名,字段名和各字段類型。
寄存器
在dalvik字節碼中,寄存器都是32位的,能夠支持任何類型。64位類型(Long和Double型)用2個寄存器表示。
有兩種方式指定一個方法中有多少寄存器是可用的。.registers指令指定了方法中寄存器的總數。.locals指令表明了方法中非參寄存器的數量。
方法的傳參
???當一個方法被調用的時候,方法的參數被置于最后N個寄存器中。如果一個方法有2個參數,5個寄存器(v0-v4),那么參數將置于最后2個寄存器——v3和v4。
???非靜態方法中的第一個參數總是調用該方法的對象。
例如,非靜態方法LMyObject;->callMe(II)V有2個整型參數,另外還有一個隱含的LMyObject;參數,所以總共有3個參數。假如在該方法中指定了5個寄存器(v0-v4),以.registers方式指定5個或以.locals方式指定2個(即2個local寄存器+3個參數寄存器)。當該方法被調用的時候,調用該方法的對象(即this引用)存放在v2中,第一個整型參數存放在v3中,第二個整型參數存放在v4中。
對于靜態方法除了沒有隱含的this參數外其它都一樣。
寄存器的命名方式
有兩種方式——V命名方式和P命名方式。P命名方式中的第一個寄存器就是方法中的第一個參數寄存器。在下表中我們用這兩種命名方式來表示上一個例子中有5個寄存器和3個參數的方法。
v0????第一個local?register
v1????第二個local?register
v2??p0??第一個parameter?register
v3??p1??第二個parameter?register
v4??p2??第三個parameter?register
你可以用任何一種方式來引用參數寄存器——他們沒有任何差別。
注意:baksmali默認對參數寄存器使用P命名方式。如果想使用V命名方式,可以使用-pl—no-parameter-registers選項。
使用P命名方式是為了防止以后如果要在方法中增加寄存器,需要對參數寄存器重新進行編號的缺點。
Long/Double值
Long和double類型是64位的,需要2個寄存器(切記切記)。
例如,對于非靜態方法LMyObject;->MyMethod(IJZ)V,參數分別是LMyObject;,int,long,bool。故該方法需要5個寄存器來存儲參數。
p0??this
p1??I
p2,p3??J
p4??Z?
#?static?fields?????????????定義靜態變量的標記
#?instance?fields????????定義實例變量的標記
#?direct?methods???????定義靜態方法的標記
#?virtual?methods??????定義非靜態方法的標記
構造函數的返回類型為V,名字為<init>。
?
if-eq?p1,?v0,?:cond_8?表示如果p1和v0相等,則執行cond_8的流程:
????:cond_8
????invoke-direct?{p0},?Lcom/paul/test/a;->d()V
調用com.paul.test.a的d()方法
if-ne?p1,?v0,?:cond_b?表示不相等則執行cond_b的流程:
????:cond_b
????const/4?v0,?0x0
????invoke-virtual?{p0,?v0},?Lcom/paul/test/a;->setPressed(Z)V
????invoke-super?{p0,?p1,?p2},?Landroid/view/View;->onKeyUp(ILandroid/view/KeyEvent;)Z
????move-result?v0
?
大概意思就是調用com.paul.test.a的setPressed方法,然后再調用父類View的onKeyUp方法,最后?return?v0?
舉兩個例子:
sget-object?v5,?Lcom/google/youngandroid/runtime;->Lit227:Lgnu/mapping/SimpleSymbol;
獲取com.google.youngandroid.runtime中的Lit227字段存入v5寄存器,相當于
gnu.mapping.SimpleSymbol?localVariable?=?com.google.youngandroid.runtime.Lit227;
sput-object?v0,?Lcom/google/youngandroid/runtime;->Lit78:Lkawa/lang/SyntaxTemplate;
設置com.google.youngandroid.runtime.Lit78的值為v0寄存器中的kawa.lang.SyntaxTemplate類型變量的值。相當于com.google.youngandroid.runtime.Lit78?=?kawa.lang.SyntaxTemplate?localVariable;
轉載于:https://www.cnblogs.com/helloZQP/p/4064971.html
總結
以上是生活随笔為你收集整理的Smali源代码分析教程(转)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 01 数据类型 、常量变量、运算符、表达
- 下一篇: 郁闷心情——电话聊天排解法