1. 程式人生 > >android反編譯----smali Wiki翻譯--暫存器

android反編譯----smali Wiki翻譯--暫存器

暫存器 Registers

描述smali檔案中暫存器的具體資訊,並概括在dalvik位元組碼中的資訊。

介紹Introduction

在dalvik位元組碼中,暫存器總是32位,能夠儲存任何型別的值。2個暫存器用來儲存64位的型別(Long和Double)。

說明方法中暫存器的個數

有兩種方法指定方法中有多少個暫存器可用。類似  .registers的指令,指明瞭方法中總的暫存器數目;另一中 .locals指令,指明瞭方法中不包括引數(函式入參)在內的暫存器數目。方法中總的暫存器數目包括儲存locals(本地變數)所需的和儲存函式引數所需的暫存器數目。

方法的引數是怎樣傳遞到方法中的?

當一個方法被呼叫時,方法的引數被放置在最後幾個暫存器中。如果一個方法有2個入參和註冊了5個暫存器(v0-v4),引數被放置在最後2個暫存器,v3和v4.

非靜態方法的第一個引數總是呼叫改方法的物件(可以理解為this指標)。

例如,你寫了一個靜態方法,LMyObject;->callMe(II)V.這個方法有2個整形引數,但是在兩個整形引數之前,它還有一個隱藏的引數LMyObject;,因此改方法的引數總數是3.

假設你通過.register 5(v0-v4)或者.locals 2指令(2個本定暫存器加3個引數暫存器),指定在方法中有5個暫存器可用。當這個方法被呼叫時,呼叫改方法的物件將被儲存在v2暫存器中,第一個整形引數儲存在v3中,第二個整形引數儲存在v4中。

靜態方法與此類似,只不過沒有隱藏的this引數。

暫存器的名稱

暫存器有2種命名設計,正常的v命名和為了引數設計的p命名。p命名方案中的p0是指方法中的第一個引數。讓我們回到上一個例子當中,方法有3個引數,共5個暫存器。下面的表格表明了v命名方案中每個v引數和相應的p命名方案中的p引數。

v0 第一個本地暫存器
v1 第二個本地暫存器
v2    p0 第一個引數暫存器
v3    p1 第二個引數暫存器
v4    p2   第三個引數暫存器

引用引數暫存器時,這兩種命名方式都可以採用。

引入引數暫存器的動機

作為一個特例,引入p命名方案的引數暫存器,是為了在編輯smali程式碼時解決一個常見的煩惱。

假設你現在有一個有大量引數的方法,並要向裡面新增一些程式碼,這時你發現你需要一個額外的暫存器。你會認為,這是一個小事,增加 .registers指令後面跟的number就好。

不幸的是,事情並不是那麼簡單,要記住的是方法的引數儲存在最後幾個暫存器當中。如果你增加暫存器的數量,你就改變了儲存方法引數的暫存器。這樣你就必須要改變.register指令並且改變每一個引數暫存器的號碼。

但是如果在方法中,p命名方法被用來指示引數暫存器,你可以簡單的改變方法中引數暫存器的數目,而不用擔心改變任何現存的暫存器的號碼。

注意:預設的,baksmali對引數暫存器使用p命名方案。如果你想把這部分功能關調,強制要求baksmali使用v命名方案,你可以使用-p/--no-parameter-registers option.

Long/Double values

正如前面所提到的,long和double型別(縮寫是J和D)是64位的值,它們需要2個暫存器。當你要引用函式引數的時候,這一點要記住。例如假設你有一個方法(非靜態的)LMyObject;->MyMethod(IJZ)V. 方法的引數是LMyObject;,int,long,bool.因此這個方法需要5個暫存器儲存引數。

p0 this
p1 I
p2,p3     J
p4 Z

並且,在你隨後呼叫這個方法得時候,你必須在呼叫指令的暫存器列表中,為任何一個double長度的引數指定一個雙暫存器。

參考官方原文: