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指令集挺像的

 

posted @ 2022-03-05 23:05  TLSN  阅读(687)  评论(0)    收藏  举报