smail语法

ads

反编译安卓APK都会生成一个smali文件,本篇文章为smali文件的语法(即Dalvik指令)速查手册,速速收藏备忘。

0.类型

Dalvik指令中的类型和java的对应关系如下:


语法 Java类型
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位类型,需要使用两个相邻的寄存器来存储。

1.方法

方法表示

方法用.method表示开始,.end method表示结束。用#来添加注释,# virtual methods表示这是一个虚方法,# direct methods表示一个直接方法

方法表示语法为:

Lpackage/name/ObjectName;->MethodName(III)Z

Lpackage/name/ObjectName;表示类型

MethodName表示ObjectName类下面的方法

III表示三个整形参数

Z表示为返回bool类型的值

例子:

method(I[[IILjava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;

对应java为:

String method(int,int[][],int,String,Object[])

方法调用


指令 含义
invoke-virtual(/range) 用于调用实例的虚方法
invoke-super(/range) 用于调用实例的父类方法
invoke-direct(/range) 用于调用实例的直接方法
invoke-static(/range) 用于调用实例的静态方法
invoke-interface(/range) 用于调用实例的接口方法


2.字段

字段表示

字段与方法类型,使用.field 表示。# instance fields表示实例字段,# static fields表示静态字段

字段表示语法为:

Lpackage/name/ObjectName;->FieldName:Ljava/lang/String;

字段操作指令

对普通字段操作,读使用iget指令,写使用iput指令。例如iget、iget-wide、iget-object、iget-boolean、iget-type、iget-char、iget-short

静态字段操作,读使用siget指令,写使用sput指令

3.寄存器

寄存器声明,可以理解为变量开辟的存储数量。使用关键.registers  、.local 、.param

.registers N表示寄存器总数为N

.local N表示为方法内的寄存器数量,通常用v字母开头表示。如:v0、v1、v2....

.param 指定方法参数名,通常用p字母开头表示。如:p0、p1、p2...

4.类型变量

声明变量,使用关键字 const

64位的常规类型的字节码添加-wide后缀,像long,double等,占两个寄存器;

特殊类型的字节码,添加特殊的后缀。可以是--boolean,-byte,-char,-short,-int,-long,-float,-double,-object,-string,-class,-void等。

对于会产生歧义的,会添加/字节码来消除歧义。

指令 move-wide/from16 vAA,vBBBB 为例,move为基础字节码,表示一个基本操作。-wide为名称后缀,表示操作的数据宽度为64位。from16为字节码后缀,表示一个来自16位的寄存器引用变量。vAA为目标寄存器,vBBBB为源寄存器

常量、字符串、类

const (/4/16/high16) vA,xx 表示将xx赋值给vA,/后面根据xx长度选择

const-wide(/16/32/high16) vAA,xxxx  表示将xxxx赋值给寄存器vAA、vAA+1 ,/后面根据xxxx长度选择

const-string(/jumbo) vAA,xxxx 表示通过字符串索引构造一个字符串并赋值给vAA,较大时使用/jumbo 后缀

const-class(/jumbo) vAA,xxxx 表示通过类型索引获取一个类引用,并赋值给vAA

数组

array-length vA,vB 指令用于获取给定vB寄存器中数组的长度,并将值赋予给vA寄存器

new-array(/jumbo) vA,vB,type@CCCC 指令用于构造制定类型(type@CCCC)和大小(vB)的数组,并将值赋予vA寄存器

filled-new-array(/range/jumbo) {vC,vD,vE,vF,vG} , type@BBBB 指令用于构造制定类型(type@BBBB)和大小 (vA)的数组并填充内容。vA是隐含使用,除了制定数组的小,还指定参数个数。vC-vG是使用的参数寄存器序列。需要指定取值范围时,filled-new-array/range {vCCCC....vNNNN} 这种格式。

fill-array-data vAA,xxxx 指令用指定的数据来填充数组

arrayop vAA,vBB,vCC 指令用于对vBB寄存器指定的数组元素进行取值与赋值。vCC 寄存器用于指定数组元素的索引。vAA寄存器用于存放读取和需要设置数据组元素的值。读取元素时使用aget指令,赋值时使用aput指令。

5.数据操作

数据操作的指令为move,数据返回指令为return

move (/16/from16) vA,vB 用于将vB寄存器的值赋予vA寄存器。

move-wide(/from16) vAAAA,vBBBB 用于将vBBBB寄存器的值赋予vAAAA寄存器

move-object(/16/from16) vAAAA,vBBBB 用于为对象赋值

move-result vAA 用于将上一个invoke调用的方法非对象结果赋予vAA寄存器。move-result-wide 表示占用连续寄存器赋值,move-result-object 表示方法对象结果赋值

move-exception vAA 表示将运行时异常保存到vAA寄存器。必须在异常处理器内使用,否则无效

return-void 表示函数从一个 void方法返回

return vAA 表示函数返回一个32为非对象值,使用8位寄存器。-wide表示64位非对象值,使用相邻两个8位寄存器,-object表示对象类型返回值。

6.类型转换与检查

check-cast(/jumbo) vAA,type@BBBB 表示将vAA中的对象引用转换成指定类型

instance-of(/jumbo) vA,vB,type@CCCC 用于判断vB中的对象引用是否可以转换成type@CCCC类型,可以vA寄存器中值为1,不可以vA值为0

new-instance(/jumbo) vAA,type@BBBB 指令用于构造一个指定类型对象的新实例,并将对象引用赋值给vAA寄存器

基本类型转换


指令 含义
neg-int(long/float/double) 对数值做减法运算
not-int(long/float/double) 对数值取反
int(long/float/double)-long(/float/double/int) 表示数值转换
int-to-byte 用于将整形转换为字节
int-to-char 用于将整形转换为字符串
int-to-shot 用于将整形转换为短整形


7.数据运算

常用的运算符:


运算符 含义
add-type 加法(+)
sub-type 减法(-)
mul-type 乘法(*)
div-type 除法(/)
rem-type 模运算(%)
and-type 与运算(AND)
or-type 或运算(OR)
xor-type 异或运算(XOR)
shl-type 左移运算(<<)
shr-type 右移运算(>>)
ushr-type 无符号数右移运算(>>)


上述运算符 vAA,vBB,vCC 指令用于将vBB与vCC进行运算,将结果保存到vAA寄存器

上述运算符/2ddr vA,vB 用于将vA与vB进行运算,将结果保存到vA寄存器中

上述运算符/lit16/lit8 vA,vB,xxx 用于将vB与常量xxx进行运算,将结果保存到vA寄存器中

8.比较

比较指令是用于对两个寄存器的值进行比较,格式为cmpxxx vAA,vBB,vCC。其中vBB与vCC是需要比较的两个寄存器或寄存器对,比较的结果放到vAA中


关键字 含义
cmpl-float 比较两个单精度浮点数,如果vBB大于vCC,则vAA为-1,等于为0,小于为1
cmpg-float 比较两个单精度浮点数,如果vBB大于vCC,则vAA为1,等于为0,小于为-1
cmpl-double 比较两个双精度浮点数,如果vBB大于vCC,则vAA为-1,等于为0,小于为1
cmpg-double 比较两个双精度浮点数,如果vBB大于vCC,则vAA为1,等于为0,小于为-1
cmp-long 比较两个长整形,如果vBB大于vCC,则vAA为1,等于为0,小于为-1


9.条件和跳转

指令跳转分为三种类型,一种goto跳转,分支switch跳转,条件跳转if

goto +AA 表示指令用于无条件跳转至指定偏移处,偏移量AA不为0

packed-switch vAA,+BBBB 分支跳转指令,vAA寄存器为switch分支中需要判断的值,BBBB指向一个packed-switch-payload格式的偏移表,表中的值是递增的偏移量

sparse-swicth vAA,+BBBB 分支跳转指令,vAA寄存器为switch分支中需要判断的值,BBBB指向一个sparse-switch-payload格式的偏移表,表中的值是递增的偏移量

if-test vA,VB,+CCCC 条件跳转质量用于比较vA寄存器和vB寄存器中的值。如果条件满足就跳转至CCCC偏移处,偏移量不能为0

if-test类型指令如下:


if-test指令 含义
if-eq 等于(==)
if-ne 不等于(!=)
if-gt 大于(>)
if-ge 大于等于(>=)
if-lt 小于 (<)
if-le 小于等于 (<=)


if-testz vAA,+BBBB 条件跳转指令将vAA寄存器的值与0比较。如果结果满足则跳转至BBBB的偏移处,偏移量不为0


if-testz指令 含义
if-eqz 为0  if(!vAA)
if-nez 不为0    if(vAA)
if-ltz 小于0   if(vAA<0)
if-gez 大于等于0   if(vAA>=0)
if-gtz 大于0   if(vAA>0)
if-lez 小于等于0   if(!vAA<=0)


10.其他

类声明

.class 类的包名及完整签名

.super 类的父类包名及完整签名

注释

smail文件用#表示注释,且只支持单行

注解

注解会添加#annotaions注释,并用.annotation指令开始,以.end annotation指令结束

行号

.line表示java源文件中的行信息

锁指令

monitor-enter vAA表示为vAA加锁

monitor-exit vAA 表示释放指定对象的锁

异常指令

throw vAA 用于抛出vAA寄存器中指定类型的异常


最后编辑于:2024/1/21 拔丝英语网

admin-avatar

英语作文代写、国外视频下载

高质量学习资料分享

admin@buzzrecipe.com