了解Dalvik寄存器的v和p命名方式

為了更好的了解反編譯代碼,有必要了解一下其中的細節(jié)部分,比如v0、v1、p1都是什么等等。
代碼還是之前的Hello.java。體會Java虛擬機和Dalvik虛擬機的架構(gòu)不同之處

public class Hello{
    public int foo(int a, int b){
        return (a + b) * (a - b);
    }

    public static void main(String[] argc){
        Hello hello = new Hello();
        System.out.println(hello.foo(5, 3));
    }
}

編譯過程不寫了,直接看dexdump的反編譯代碼:這里我們還是只分析foo()函數(shù)。

  Virtual methods   -
    #0              : (in LHello;)
      name          : 'foo'
      type          : '(II)I'
      access        : 0x0001 (PUBLIC)
      code          -
      registers     : 5
      ins           : 3
      outs          : 0
      insns size    : 6 16-bit code units
000198:                                        |[000198] Hello.foo:(II)I
0001a8: 9000 0304                              |0000: add-int v0, v3, v4
0001ac: 9101 0304                              |0002: sub-int v1, v3, v4
0001b0: b210                                   |0004: mul-int/2addr v0, v1
0001b2: 0f00                                   |0005: return v0
v命名方法

從代碼中我們可以看到foo一共使用了5個寄存器,上個章節(jié)中我們也說了,add-int v0, v3, v4中v3和v4分別代表第一個參數(shù)和第二個參數(shù)。那么為什么是這樣呢?

規(guī)則:

根據(jù)Dalvik虛擬機參數(shù)傳遞的規(guī)則,如果一個函數(shù)使用了M個寄存器、擁有N個參數(shù):則參數(shù)使用最后N個寄存器,局部變量從v0開始一直遞增到前M-N個。

那我們來分析下,foo()函數(shù),一共是5個registers寄存器,有兩個int的參數(shù)。由于foo函數(shù)是Hello類的非靜態(tài)方法,因此函數(shù)被調(diào)用時會傳入一個“隱藏”的Hello對象引用(this),所以實際傳參是3個。也就是局部變量使用v0和v1寄存器,參數(shù)使用v2、v3、v4這三個后面的寄存器。其中v2表示被傳入的“隱藏”的對象引用(this)、v3表示第一個參數(shù)、v4表示第二個參數(shù)。

p命名方法

p命名方法對函數(shù)的局部變量寄存器命名沒有影響。他的命名規(guī)則是:函數(shù)引用的參數(shù)從p0開始命名,依次遞增。

使用ddx.jar反匯編Hello.dex文件,這樣會在目錄下生成一個ddxout文件夾,用文件編輯器打開里面的Hello.ddx文件。

$ java -jar /Users/johnhao/Downloads/tools/smali/ddx.jar -d ddxout /Users/johnhao/Downloads/Train/Hello.dex
Processing Hello

來看一下foo()函數(shù),依然是使用5個寄存器:

.method public foo(II)I
.limit registers 5
; this: v2 (LHello;)
; parameter[0] : v3 (I)
; parameter[1] : v4 (I)
.line 3
    add-int v0,v3,v4
    sub-int v1,v3,v4
    mul-int/2addr   v0,v1
    return  v0
.end method

v0和v1表示局部變量的寄存器,p0、p1、p2表示函數(shù)引用參數(shù)的寄存器,其中p0表示被傳入的Hello對象的引用(this)、p1表示第一個int參數(shù)、p2表示第二個int參數(shù)。

比較

v命名相比較p命名,大體結(jié)構(gòu)相同,有一些細微的地方。
1、v命名以.registers開頭,p命名以.limit 開頭
2、v命名以v2作為this的引用,p命名以p0作為this的引用
3、v命名以M-N命名N個參數(shù)的寄存器,p命名則用p命名法。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容