在 的字节码中,寄存器都是 32 位的,能够用来储存所有类型的值。对于 long和 这样占用64 位的类型,使用两个寄存器存放。 指定方法的寄存器个数 有两种方法来指定某个方法中有多少个可用的寄存器。 . 指示符指定方法中的寄存器总数,另一种 . 指示符指定方法中的非参数寄存器的个数,寄存器的总数也包括用来存放参数的寄存器的个数。 传递给方法的参数个数 当一个方法被调用时,方法的参数被放入最后n 个寄存器。如果方法a 有2 个参数,5个寄存器(v0-v4)那么参数将被放入最后2 个寄存器v3 和v4 中。 非静态方法的第一个寄存器总是存放着调用这个方法的对象。例如,如果你写了一个非静态方法 ;->(II)V. 这个方法有两个整数参数,但是它也有一个隐式的;类型参数,所以这个方法总共有3 个参数。 如果你要在方法中指定5 个寄存器(v0-v4) 那么可以使用 . 5 或者. 2 指示符。当这个方 法被调用时,调用对象将会存储在v2 中,第一个整数参数在v3 中,第二个整数参数在v4 中。
对于静态方法来说是类似的,除了没有隐式的调用对象参数。 寄存器名 寄存器有两种命名形式,普通的v 形式和参数寄存器的p 形式。p 形式中的第一个寄存器是方法的第一个参数的寄存器。所以之前的例子中,3 个参数和5 个寄存器使用v 形式和p 形式的命名方法如下: v0the first local v1the local v2 p0 the first v3 p1 the v4 p2 the third 你可以通过任何一种命名方式引用寄存器,这二者没有任何不同。 引入参数寄存器的动机 p 形式的命名方式的引入是为了解决编写Smali 代码时的一个实际问题。假如有一个已有的方法,你想加入一些代码来扩充其功能,并且你发现你需要一个额外的寄存器。你可能会想,没什么大不了的,我只需要增加 . 指示符后面指定的寄存器数量就行。 不幸的是,事实没有那么简单。记住,方法的参数存储在方法的最后n 个寄存器中。
如果你增加了寄存器的数量,就改变了方法参数所在的寄存器,所以你将不得不重命名所有的参数寄存器。 但是如果使用p 形式的命名形式在方法中引用参数寄存器,你可以简单的改变方法的寄存器的数量,不需要担心为已存在的寄存器重新编号。 注: 默认情况下使用p 命名形式表示参数寄存器。如果你想强制 使用v 命名形式,可以使用-p/–no-- 选项。 Long/ 之前提到,long 和 类型(J 和D)是64 位的值,需要2 个寄存器。当你引用方法的参数时需要格外注意。例如,你有一个非静态方法;->(IJZ)V, 寄存器的分配方式如下: p0 this p1 I p2, p3 Jp4 Z********************************************************************************************************************************说白了,就是不要用.,不然增加寄存器的时候p1,p2 会改得自己又晕又痛苦。
直接用. 就好,表示非参寄存器有多少,后面到p0,p1,p2 自动调整。所以,即使想增加寄存器,直接改. 后面跟的数字就好了。重点PS:在增加了. 后,pX 就自动往后移了,这个时候,对于某些语句,比如什么move- 就可能不适用了,因为move- 后面跟的参数是4bit。这个时候,就查表调整吧。心一黑,全换成move-/16 也不是不可以。
评论(0)