Android】【转】Smail的寄存器

来源:互联网 发布:c++游戏编程 编辑:程序博客网 时间:2024/05/17 02:12
原文出自Smali项目的Wiki http://code.google.com/p/smali/wiki/Registers


在Dalvik的字节码中,寄存器都是32位的,能够用来储存所有类型的值。对于long和double这样占用64位的类型,使用两个寄存器存放。


指定方法的寄存器个数


有两种方法来指定某个方法中有多少个可用的寄存器。 .registers指示符指定方法中的寄存器总数,另一种 .locals指示符指定方法中的非参数寄存器的个数,寄存器的总数也包括用来存放参数的寄存器的个数。


传递给方法的参数个数


当一个方法被调用时,方法的参数被放入最后n个寄存器。如果方法a有2个参数,5个寄存器(v0-v4)那么参数将被放入最后2个寄存器v3和v4中。


非静态方法的第一个寄存器总是存放着调用这个方法的对象。例如,如果你写了一个非静态方法LMyObject;->callMe(II)V. 这个方法有两个整数参数,但是它也有一个隐式的LMyObject;类型参数,所以这个方法总共有3个参数。


如果你要在方法中指定5个寄存器(v0-v4) 那么可以使用 .registers 5或者.locals 2指示符。当这个方法被调用时,调用对象将会存储在v2中,第一个整数参数在v3中,第二个整数参数在v4中。


对于静态方法来说是类似的,除了没有隐式的调用对象参数。


寄存器名


寄存器有两种命名形式,普通的v形式和参数寄存器的p形式。p形式中的第一个寄存器是方法的第一个参数的寄存器。所以之前的例子中,3个参数和5个寄存器使用v形式和p形式的命名方法如下:
v0   the first local register
v1   the second local register
v2 p0 the first parameter register
v3 p1 the second parameter register
v4 p2 the third parameter register


你可以通过任何一种命名方式引用寄存器,这二者没有任何不同。


引入参数寄存器的动机


p形式的命名方式的引入是为了解决编写Smali代码时的一个实际问题。假如有一个已有的方法,你想加入一些代码来扩充其功能,并且你发现你需要一个额外的寄存器。你可能会想,没什么大不了的,我只需要增加 .registers指示符后面指定的寄存器数量就行。


不幸的是,事实没有那么简单。记住,方法的参数存储在方法的最后n个寄存器中。如果你增加了寄存器的数量,就改变了方法参数所在的寄存器,所以你将不得不重命名所有的参数寄存器。


但是如果使用p形式的命名形式在方法中引用参数寄存器,你可以简单的改变方法的寄存器的数量,不需要担心为已存在的寄存器重新编号。
注:baksmali默认情况下使用p命名形式表示参数寄存器。如果你想强制baksmali使用v命名形式,可以使用-p/–no-parameter-register选项。


Long/double


之前提到,long和double类型(J和D)是64位的值,需要2个寄存器。当你引用方法的参数时需要格外注意。例如,你有一个非静态方法LMyObject;->MyMethod(IJZ)V, 寄存器的分配方式如下:
p0 this
p1 I
p2, p3 J
p4 Z




********************************************************************************************************************************


说白了,就是不要用.register,不然增加寄存器的时候p1,p2会改得自己又晕又痛苦。
直接用.locals就好,表示非参寄存器有多少,后面到p0,p1,p2自动调整。所以,即使想增加寄存器,直接改.locals后面跟的数字就好了。


重点PS:在增加了.locals后,pX就自动往后移了,这个时候,对于某些语句,比如什么move-object就可能不适用了,因为move-object后面跟的参数是4bit。这个时候,就查表调整吧。心一黑,全换成move-object/16也不是不可以。
0 0
原创粉丝点击