欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

android反编译----smali Wiki翻译--寄存器

程序员文章站 2022-07-13 15:42:53
...
寄存器 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长度的参数指定一个双寄存器。