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長度的引數指定一個雙暫存器。
參考官方原文: