smali学习之Dalvik寄存器
一、 Dalvik寄存器
1、大小
Dalvik寄存器为32位
 
Java实验代码:
 
在定义变量类型的时候,boolean,short,char虽然不为4个字节,但也是要占一个32位
的寄存器。而对于long,double等类型,数据宽度大于4字节,会使用两个4字节寄存器
 
虽然在smali文件中并没有显示他们使用两个寄存器(如图中的long)
2、 寄存器的命名
 
 
看这里的寄存器名一般为v开头的,但在main函数下两行,有一个p开头的寄存器表示参数 p0 args
3、 Main函数
 
一个[ 表示一个数组
L表示类
Java/lang/String 表示包名和类名(完整类名)
4、 Dalvik字节码类型与java基本数据类型的关系
 
 
二、 Dalvik字段
我们在原来的源代码上添加一些
 
编译一下,查看smali文件
 
可以看到,多了静态字段与实例字段
下面我们看看操作字段
1、操作字段
 
(一)、sget-object v10
s代表 static
get 代表获取
sget就是获取静态字段的值
object表示操作字段的类型
V10表示out返回的结果
(二)、Ljava/lang/System;->out:Ljava/io/PrintStream
Out是字段名
Ljava/io/PrintStream是字段类型,字段名与字段类型之间要用:隔开
L表示后面跟着类名
Java/lang/是包名
System;是类名
Ljava/lang/System;表示当前out字段所在的类
Ljava/io/PrintStream;表示out字段的类型
一整个 就是获取静态字段out的值,返回值是一个类
2、方法的表现形式
 
如例2
Landroid/app/Activity表示方法所在类
onCreate表示方法名
()里面表示参数
V表示返回值
3、实例化对象
 
V11寄存器用来保存Ljava/lang/stringBuilder实例化后的对象
 
 
所有实例化对象都是在构造方法中进行初始化的
4、 方法调用
Invoke表示调用方法 – 直接方法(静态方法、构造方法、静态语句块)
(一)、invoke直接调用
 
该语句表示invoke调用一个直接方法,直接方法是StringBuilder提供的无参构造方法
3与4连起来就是 StringBuilder v11 = new StringBuilder();
(二)、invoke调用虚方法(java代码中除直接调用方法外都是虚方法)
 
v11.append(v1)
这个函数有返回值,所以其下有一行 move-result-object v11
所以函数源代码应该是:
StringBuilder v11 = v11.append(v1) ps:v1是int类型的
5、const-string
 
定义Stirng类型的局部变量并初始化
三、 Dalvik指令集
 
指令集,上节课我们学到的
Move-result-object(接收类返回值)
Sget-object(操作字段)
New-instance
Invoke
If-eqz(默认与零比较)
Const/4(定义四位的常量)
Const-wide (定义64位的常量)
Const
等等都是指令集
0、前叙
 
1、mov-result 接收方法的返回值
返回结果类型为类的化,使用 mov-result-object
返回结果类型为double或long的化,使用mov-result-wide
其他一般的数据类型还是使用mov-result
有的地方甚至不加mov
2、Getlong函数
 
看其smali文件
 
我们会发现,有三个register,但long类型只占两个寄存器的大小,这是为什么?
因为这不是static定义的方法,函数内默认有一个this指针指向数据对象,this指针占了一个寄存器
 
还有就是,getlang函数调用printf函数,传进去了v1,v2,v3三个寄存器,v1,v2都有迹
可循,v3却找不到,其实,由于输出的数为long类型,一个v2寄存器存不下,v3是扩充的
数据类型指令集
 
3、short,byte类型
我们的short类型,byte类型的定义都是const/16 也就是16位的
4、Integer类型
 
先定义基本数据类型 0x270f(是我初始化传递的参数)
然后调用构造函数
最后move-result-object返回对象
5、列表指令
 
 

实例化,invoke方法调用构造,起别名??
6、数组指令
 
 
先定义赋值给 v14,invoke调用函数,返回值为B类型的数组(byte类型的数组)
返回对象给v7
起别名
7、 String数组
 
 
 
V3 0x2
意思是定义一个二维数组
V1,0x5
意思是含有5个参数
然后调用数组指令v0保存实例数组
Const/4 V1,0x0 v1变成下表
const-string v2, "12" 为v2赋值
aput-object v2, v0, v1 在索引为v1(0)的位置填充v2于v0
const/4 v1,0x1
const-string v2, "345"
aput-object v2, v0, v1
这些语句同理,v1为下表,v2为数据,v0为数组
下面是字符串数组的输出
 
 
aget-object v2, v0, v3
还是上面的数组操作,索引,数据,数组
V1获取静态字段
传参到printlf输出
8、三种put
 
9、 switch语句
 
 

可以看到,我们case的索引是非连续的,所以 使用的是 sparse-switch指令
看smali代码,我们对v0起别名,执行sparse-switch后触发 :sswitch_data_6 跳转
根据v0的值选择跳转到哪里,由于,源代码都是break; 所以跳转的位置也都是 :sswitch_4
我们更改case语句
更改源代码:
 
Smali代码:
 
 
 
可以看到,smali代码中底部的跳转指令变得都不一样了
10、 条件指令
 
 
11、 aget
 
12、aput
 
13、iget
 
获取实例字段
14、 iput
设置实例字段
 
15、 sget
 
获取静态字段值
16、 sput
 
设置静态字段值
17、invoke
 
 
 
18、数据转换指令
类似于:
 
 
19、数据运算指令
 
与intelx86指令集挺像的

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号