3 Dalvik基础知识
Dalvik汇编基础知识:
Dalvik指令:由位描述+指令格式标示
位描述:
1. 每16位空格隔开
2. 每个字母表示4位,每个字母按从高字节开始,排列到低字节。每四位之间可用 | 分开表示不同内容
3. 顺序采用A~Z单个大写字母作为一个4位操作码,op表示一个8位操作码
4. Ø表示这字段所有位为0
Eg:A|G|op BBBB F|E|D|C
分成三部分:A|G|op 高8位是A G 低8位是op
BBBBB 一个16位的偏移值
F|E|D|C 表示寄存器参数
指令格式:
1. 大多有三个字符组成,前两个是数字,后一个是字母
2. 第一个数字表示指令有多少个16位的字
3. 第二个数字表示指令最多使用的寄存器个数,“r”标示使用一定范围内的寄存器
4. 第三个字母为类型码
助记符 |
位大小 |
说明 |
b |
8 |
8位有符号立即数 |
c |
16,32 |
常量池索引 |
f |
16 |
接口常量(仅静态有效) |
h |
16 |
有符号立即数(32位或64位的高值位,低值位为0) |
i |
32 |
立即数,有符号整数或32位浮点数 |
l |
64 |
立即数,有符号或64位双精度浮点数 |
m |
16 |
方法常量(仅静态有效) |
n |
4 |
4位立即数 |
s |
16 |
短整形立即数 |
t |
8,16,32 |
跳转,分支 |
x |
0 |
无额外数据 |
Eg:22x 两个16位字,2个寄存器,无额外数据
Dalvik语法:
1. 每条指令从操作码开始,后面紧跟参数,参数之间由逗号隔开
2. 每条指令的参数从指令第一部分开始,op位于低8位,高8位可以是一个8位参数,两个4位参数或空,超过16位,指令后面部分依次作为参数
3. 参数“vX”表示是一个寄存器
4. 参数“#+X”表示常量数字
5. 参数“+X”表示地址偏移
6. 参数“kind@X”表示常量池索引,kind可以是:string,type,field,meth
Dalvik寄存器:
Dalvik虚拟机基于ARM架构,将部分寄存器映射到ARM寄存器上,其余的通过调用栈模拟
说明:Dalvik寄存器是32位。支持64位,两个相邻的寄存器标示
Eg: op vAAAA,vBBBB 寄存器从v0开始,寄存器可能的范围 0~65535
每个函数的头部 .registers 指定函数使用的寄存器数目
寄存器--V和P命名法
假设一个函数有M个寄存器N个参数:
V:从v0开始依次递增
P:函数使用的寄存器从v0开始依次递增,参数从p0开始依次递增
一、Dalvik类型:
Dalvik字节码只有两种类型:
1. 基本类型:除对象,数组,其他的java类型
2. 引用类型:对象,数组
字节码描述符
语法 |
含义 |
V |
void 只用于返回值类型 |
Z |
boolean |
B |
byte |
S |
short |
C |
char |
I |
int |
J |
long |
F |
float |
D |
double |
L |
Java类类型 |
[ |
数组类型 |
说明:Dalvik寄存器是32位表示象J 、D 等64位数据类型两个相邻的寄存器存储
L Ljava/lang/String; 后面有 ;表示结束,相当于 java.lang.String
[ 后面紧跟基本类型描述符
[I 一维整形数组 int[]
[[I 二维整形数组 int[][]
[[[I 三维整形数组 int[][][]
数组最大维数255个
L和[同时表示对象数组
[Ljava/lang/String; Java中的字符串数组
二、Dalvik方法
使用方法名,类型参数,返回值描述一个方法
Eg:Lpackage/name/ObjectName;->MethodName(III)Z
Lpackage/name/ObjectName; 一个类型
MethodName 方法名
(III) 三个int型参数
Z 返回值类型为void
method(I[[IILjava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
等价于:String method(int ,int[][] ,int ,String ,Object[])
三、Dalvik字段
字段与方法类似,没有方法的参数和返回值
Eg:Lpackage/name/ObjectName;->FiledName:Ljava/lang/String;
Lpackage/name/ObjectName; 包名
FiledName 字段名 用:隔开字段类型
Ljava/lang/String; 字段类型
#注释
Dalvik指令特点:
1. 参数从目标到源
2. 根据字节码大小和类型添加后缀
a) 32位常规类型没有后缀
b) 64位类型添加- wide后缀
c) 特殊类型字节码根据具体类型添加后缀:boolean, byte, char, short, int, long, float, double, object, string, class, void
3. 根据字节布局与选项添加字节码后缀消除歧义。这些后缀通过字节码主名“/”分隔
4. 指令集中每个字母宽度为4
Eg:move-wide/from16 vAA,vBBBB
move为基础字节码,标示基本操作
wide 为名称后后缀,标示指令操作的数据宽度(16位)
from16 为字节码后缀,标示一个16位的寄存器引用变量
vAA 为目的寄存器,始终在源寄存器前
vBBBB 为源寄存器
空操作指令 nop 值为0,常用来对齐操作,无实际操作
数据操作指令 move
move 格式:move 目标寄存器,源寄存器 move根据字节码的大小与类型,后会跟上不同后缀
返回指令 return
返回函数结尾时运行的最后一条指令。
数据定义指令 用来定义程序中的常量,字符串,类等数据,基础字节码 const
const 格式:const 目标寄存器,源寄存器 const根据字节码的大小与类型,后会跟上不同后缀
锁指令 有两种:
monitor-enter vAA 为指定对象获取锁
monitor-exit vAA 释放指定对象的锁
实例操作指令:包括类型转换,检查,新建等
check-cast vAA,type@BBBB 将vAA寄存器中的对象引用转换成指定类型,失败抛出ClassCastException异常,如果B是基本类型,A非基本类型则会失败
instance-of vA,vB,type@CCCC 判断vB寄存器对象类型转换是否成功,成功vA为1,失败vA为0
new-instance vAA,type@BBBB 构造指定类型对象的新实例,将对象引用给vAA,类型符type不能是数组类
check-cast/jumbo vAAAA,type@BBBBBBBB
instance-of/jumbo vAAAA,type@CCCCCCCC
new-instance/jumbo vAAAA,type@BBBBBBBB
数组操作指令:
获取数组长度,新建数组,数组赋值,数组元素赋值取值操作
arrary-length vA,vB 获取vB数组长度给vA(数组长度:特指数组的条目个数)
new-array vA,vB,type@CCCC 构造type@CCCC类型,长度vB的数组,赋给vA
filled-new-array {vC,vD,vE,vF,vG},type@BBBB 构造type@BBBB类型,长度vA(vA寄存器市隐含使用)的数组,并填充数组内容vC~vG是参数寄存器序列
filled-new-array/range{vCCCC...vNNNN},type@BBBB 功能同上,参数寄存器使用range字节码后缀指定取值范围
fill-array-data vAA,+BBBBBBBB 用指定数据填充数组,vAA为数组引用(必需是基础类型),指令后跟一个数据表
new-array/jumbo vAAAA,vBBBB,type@CCCCCCCC
arrayop vAA,vBB,vCC 对vBB寄存器指定的数组元素进入取值与赋值,vCC指定数组元素索引,vAA存放读取的或需要设置的数组元素的值。读取用aget指令,赋值用aput类指令。
异常指令
throw vAA
跳转指令:
三种跳转指令,无条件跳转(go-to),分支跳转(switch),条件跳转(if)
goto +AA
goto/16 +AAAA
goto/32 +AAAAAAAA
packed-switch vAA,+BBBBBBBB
sparse-switch vAA,+BBBBBBBB
if-test vA,vB,+CCCC
if-test类型:
if-eq vA == vB
if-ne !=
if-lt <
if-ge >=
if-gt >
if-le <=
if-testz vAA,+BBBB
if-eqz == 0
if-nez !=0
if-ltz <0
if-gez >=0
if-gtz >=0
if-lez <=0
比较指令:
cmpkind vAA,vBB,vCC vBB和vCC比较结果存放到vAA vBB>vCC 结果-1 vBB==vCC结果0 vBB<vCC结果1
cmpl-float
cmpg-float
cmpl-double
cmpg-double
cmp-long
字段操作指令:
用来对对象实例的字段进行读写操作
普通字段:iinstanceop vA,vB,field@CCCC
普通字段指令前缀i,读操作iget,写操作iput
静态字段:staticop vAA,field@BBBB
静态字段指令前缀s,读操作sget,写操作sput
根据字段类型不同,字段操作后面会紧跟字段类型后缀,两类指令操作结果一样,只是指令前缀与操作字段类型不同
方法调用指令
负责类的调用类的实例方法,基础指令invoke分两类:
1. invoke-kind {vC,vD,vE,vF,vG},meth@BBBB
2. Invoke-kind{vCCCC...vNNNN},meth@BBBB
根据方法类型不同,共有5条方法调用指令
1.invoke-virtual invoke-virtual/range 调用实例的虚方法
2.invoke-super invoke-super/range 调用实例的父类方法
3.invoke-direct invoke-direct/range 调用实例的直接方法
4.Invoke-interface invoke-interface/range 调用实例的接口方法
数据转换指令:
格式unop vA,vB vB需要转换的数据,vA转换后的结果
neg-int int数 求补
not-int 求反
neg-long long
not-long
neg-float
neg-double
int-to-long int转long
int-to-float
int-to-double
long-to-int
long-to-float
long-to-double
float-to-int
float-to-long
float-to-double
double-to-int
double-to-long
double-to-float
int-to-byte
int-to-char
int-to-short
数据运算指令
有4类指令:
1. binop vAA,vBB,vCC vBB与vCC计算结果保存到vAA
2. Binop/2addr vA,vB
3. Binop/lit16 vA,vB,#+CCCC
4. Binop/lit8 vAA,vBB,#+CC
第一类指令可归结为:
add-type
sub-type
mul-type
div-type
rem-type 摸运算
and-type
or-type
xor-type
shl-type 有符号左移
shr-type 有符号右移
ushr-type 无符号右移
3 Dalvik基础知识的更多相关文章
- APK反编译之一:基础知识—APK、Dalvik字节码和smali文件
refs: APK反编译之一:基础知识http://blog.csdn.net/lpohvbe/article/details/7981386 APK反编译之二:工具介绍http://blog.csd ...
- JVM基础知识(1)-JVM内存区域与内存溢出
JVM基础知识(1)-JVM内存区域与内存溢出 0. 目录 什么是JVM 运行时数据区域 HotSpot虚拟机对象探秘 OutOfMemoryError异常 1. 什么是JVM 1.1. 什么是JVM ...
- 【Xamarin开发 Android 系列 4】 Android 基础知识
原文:[Xamarin开发 Android 系列 4] Android 基础知识 什么是Android? Android一词的本义指“机器人”,同时也是Google于2007年11月5日宣布的基于Li ...
- Android基础知识(一)
前言 前言 从软件测试最终目的发现问题缺陷来看,Findyou比较认同一个观念,测试的能力大致可以划分成三个能力层次:发现问题.定位问题.预防问题.有机会探讨一下这个分类. 发现问题各种方式方法,比如 ...
- .NET面试题系列[1] - .NET框架基础知识(1)
很明显,CLS是CTS的一个子集,而且是最小的子集. - 张子阳 .NET框架基础知识(1) 参考资料: http://www.tracefact.net/CLR-and-Framework/DotN ...
- RabbitMQ基础知识
RabbitMQ基础知识 一.背景 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然 ...
- Java基础知识(壹)
写在前面的话 这篇博客,是很早之前自己的学习Java基础知识的,所记录的内容,仅仅是当时学习的一个总结随笔.现在分享出来,希望能帮助大家,如有不足的,希望大家支出. 后续会继续分享基础知识手记.希望能 ...
- selenium自动化基础知识
什么是自动化测试? 自动化测试分为:功能自动化和性能自动化 功能自动化即使用计算机通过编码的方式来替代手工测试,完成一些重复性比较高的测试,解放测试人员的测试压力.同时,如果系统有不份模块更改后,只要 ...
- [SQL] SQL 基础知识梳理(一)- 数据库与 SQL
SQL 基础知识梳理(一)- 数据库与 SQL [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5902856.html 目录 What's 数据库 ...
随机推荐
- arduino驱动步进电机
https://learn.adafruit.com/adafruit-motor-shield-v2-for-arduino/install-software 1安装库 Adafruit_Motor ...
- Python面向对象 | 类空间及类之间的关系
一. 类的空间问题 1何处可以添加对象属性 class A: def __init__(self,name): self.name = name def func(self,sex): self.se ...
- datatime模块的使用
dt_now = datetime.datetime.now()print(dt_now)# 2019-05-09 14:44:32.555337 获取日期,不含时分秒today = dt_now.d ...
- 【CSP-S膜你考】不怕噩梦 (模拟)
不怕噩梦 题面 蚊子最近经常做噩梦,然后就会被吓醒.这可不好.. 疯子一直在发愁,然后突然有一天,他发现蚊子其实就是害怕某些事. 如果那些事出现在她的梦里,就会害怕. 我们可以假定那个害怕的事其实是一 ...
- 【主席树启发式合并】【P3302】[SDOI2013]森林
Description 给定一个 \(n\) 个节点的森林,有 \(Q\) 次操作,每次要么将森林中某两点联通,保证操作后还是个森林,要么查询两点间权值第 \(k\) 小,保证两点联通.强制在线. L ...
- 特征值、特征向量与PCA算法
一.复习几个矩阵的基本知识 1. 向量 1)既有大小又有方向的量成为向量,物理学中也被称为矢量,向量的坐标表示a=(2,3),意为a=2*i + 3*j,其中i,j分别是x,y轴的单位向量. 2)向量 ...
- libevent笔记3:evbuffer
evbuffer 之前提到bufferevent结构体提供两个缓存区用来为读写提供缓存,并自动进行IO操作.这两个缓存区是使用Libevent中的evbuffer实现的,同样,Libevent中也提供 ...
- iis可以运行但是界面不能在桌面显示是怎么回事
iis可以运行但是界面不能在桌面显示是怎么回事 引用:https://zhidao.baidu.com/question/1948053642075906588.html 在开始->运行 执行i ...
- docker 挂载主机目录 -v 和 --mount区别
使用-v 时,如果宿主机上没有这个文件,也会自动创建, 但是如果使用--mount时,宿主机中没有这个文件会报错找不到这个文件,并创建失败
- 用简单的JS代码制作计算器
代码+注释一共不到200行,是练习交流的必备良药 主界面如下: 操作示意图: 以下是代码部分 HTML: <div> <table class="window"& ...