Smali Registers
介绍Smali中Register相关知识
简介
Dalvik字节码中,register(寄存器)一定是32位,它可以用于存放任何类型的值。如果需要存放64位的数据(比如Long和Dobule),则需要两个寄存器。
有两种方法可以指定一个方法中用到的寄存器数目。.registers num指令用于指定该方法中用到的寄存器数目,.locals num指令可以指定该方法中非参数寄存器的数目。
当函数被调用时,其参数被存放在最后几个寄存器中。假如一个函数有2个参数a,b,总共有5个寄存器(v0-v4), 那么最后两个寄存器v3和v4用于存放参数a和b
一个非static成员函数的第一个参数总是调用此函数的对象即this对象
例如,LMyObject;->callMe(II)V,callMe有两个参数其类型均为整形,另外他还有一个隐式参数其类型是LMyObject,所以改方法总共有三个参数。
假定此函数有5个寄存器(v0-v4),你可以用指令.registers 5或者.locals 2(2个local寄存器和3个参数寄存器)。当此函数被调用时,第一个参数是调用此函数的对象即this对象被存放在v2,第一个整形参数存放在v3,第二个整形参数存放在v4中。
对于static 成员函数和非static成员函数的差异在于static 成员函数的参数不包含this对象
寄存器有两种命名形式普通形式vx以及参数寄存器px。P0代表第一个参数。我们现在再回到前面的例子,一个具有三个参数的函数,总共有5个寄存器,下表可以显示普通寄存器和参数寄存器的关系。
v0 | 第一个本地寄存器 | |
v1 | 第二个本地寄存器 | |
v2 | p0 | 第一个参数寄存器 |
v3 | p1 | 第二个参数寄存器 |
v4 | p2 | 第三个参数寄存器 |
你可以使用任何一种命名方式。
参数寄存器引入是为了解决修改smali代码带来的麻烦。
假定你有一个方法具有几个参数,现在你需要增加一些code到此方法中,此时你需要比原来更多的寄存器。或许你认为这没有什么,我可以修改.registers指令增加寄存器个数。
不幸的事,事情并没有那么简单。请记住,函数的参数存放在最后几个寄存中。如果你.register num指令增加函数的寄存器数目,那么参数对应的寄存器编号就发生了改变。所以你在使用 .register num指令增加函数的寄存器数目的同时 必须对参数寄存器重新编号。
但是如果用px方式命名,并且对参数的引用都是用px,则当需要增加寄存器数目的时候,事情就变得简单了,因为p0始终是第一个参数。
注意:baksmali默认使用px方式命名参数寄存器,如果你一定要使用vx方式,你可以使用-p/--no-parameter-registers选项
如前所述,long型(J)和double型(D)都是64位,需要两个寄存器来存放其值。当你使用这样的参数的时候请务必记住这一点。例如,有一个非静态成员函数LMyObject;->MyMethod(IJZ)V,此函数的参数是LMyObject;, int, long, bool,一共需要5个寄存器来存放所有的参数。
p0 | this |
p1 | I |
p2, p3 | J |
p4 | Z |
另外,以后用invoke-指令调用此方法时,你必须对double-wide参数的两个寄存器都要赋值。
原文: https://code.google.com/p/smali/wiki/Registers