1、基础
1、变量类型
B—byte
C—char
D—double
F—float
I—int
S—short
V—void
J—long
Z—boolean
2、运算符
Smali |
含义 |
符号 |
eq |
equals |
== |
ne |
not equals |
!= |
lt |
less than |
< |
gt |
bigger than |
> |
le |
less and equals |
<= |
ge |
bigger and equals |
>= |
eqz |
equals zero |
=0 |
nez |
not equals zero |
!=0 |
ltz |
less than zero |
<0 |
btz |
bigger than zero |
>0 |
gez |
bigger and equals zero |
>=0 |
lez |
less and equals zero |
<=0 |
3、关键字
// L 代表一个对象类型
//.class 表示一个类,pulic 代表公有 ,后面是全包名
// ; 分号作为语句结尾
.class public Lcom/zk/demo/MainActivity;
//.super 表示父类
.super Landroid/support/v7/app/AppCompatActivity;
//.source 代表类所在的文件名
.source "MainActivity.java"
// # 声明
// .implements (实现接口 一般在文件顶部) <实现的接口>
# interfaces
.implements Ljava/lang/Runnable;
// 直属方法 当前类所有的,不可被覆写的方法 一般是 私有/静态方法、及静态构造方法
# direct methods
// 虚方法 当前类实现,但是可以被 子类覆写的方法,多为 public/protect/inteface 的方法
# virtual methods
//代码所属行数
. line
// 局部变量 寄存器申请数
.locals N
// 方法的形参 非静态参数 p0 代指this ; p1 代指第一个形参 ,静态函数 p0 代指第一个参数
// .param [形参变量][形参名][形参类型]
.param p1, "msg" # Ljava/lang/String;
//方法开始位置
.prologue
// 结束位置
.end field / mehod / annotation
//创建实例 new-instance v1, Lcom/example/zhaokai/demo/Test;
new-instance
// 获取 变量
sget-object
// 赋值
iput-object
4、字段
// # 后面跟声明 标识接下来的类型 <static 静态> 、<instance 实例>
# instance fields
.field private isPayTest:Z
# static fields
// .field 表示后面跟的是字段类型,结合上面语句代表 当前字段
//REQUEST_CODE 是个私有静态的int类型
// : 前面是字段名称,后面则是字段类型 ,= 后面则是字段的赋值
// 格式 .field <访问权限> <静态> <不可更改> <变量名> : <变量类型> = <赋值>
.field private static final REQUEST_CODE:I = 0x186b4
5、方法
//.method [方法权限]{[abstract/static/final] [varargs] }[方法名](形参类型 形参类型)[返回值类型]
.method protected setMsg(Ljava/lang/String;Ljava/lang/String;)V
//方法内局部变量数(不包含形参)
.locals 1
.param p1, "msg" # Ljava/lang/String;
// 形参 可变形参 用数组标识 #[Ljava/lang/String;
// 行数
.line 31
//…… 执行方法
.line 32
return-void
//无返回值 returen-object 返回指定值
//方法结束
.end method
6、局部变量
//本地寄存器(local register,非参寄存器)用v开头数字结尾的符号来表示,如v0、v1、v2、…,
// locals 1 对应一个本地寄存 v0
//参数寄存器(parameter register)用p开头数字结尾的符号来表示,如p0、p1、p2、…,p0 默认为this
7、赋值获取
sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
//获取参数值 变量名,对象类型 -> 获取方法 : 获取对象类型
iput-boolean v0, p0, Lcom/example/zhaokai/demo/Test;->isTest:Z
//给参数赋值
sget/sput: static 对已标识的静态字段执行已确定的对象静态字段运算
iget/iput: instance 对已标识的字段执行已确定的对象实例字段运算
aget/aput: array 在给定数组的已标识索引处执行已确定的数组运算
sget-类型 [wide/boolean/object/byte/char/short]
8、方法执行
//返回值
move-result-object v3
//调用指定的方法。所得结果(如果有的话)可能与紧跟其后的相应 move-result* 变体指令一起存储。
invoke-virtual {v0, v1}, Ljava/io/PrintStream;->print(Ljava/lang/String;)V
//使用 invoke-virtual 调用正常的虚方法(该方法不是 private、static 或 final,也不是构造函数)
invoke-direct {v0, v1}, Lcom/example/zhaokai/demo/Test;->print(Ljava/lang/String;)Ljava/lang/String;
//invoke-direct 用于调用非 static 直接方法(也就是说,本质上不可覆盖的实例方法,
// 即 private 实例方法或构造函数)
invoke-static {v2}, Lcom/example/zhaokai/demo/Test;->setVERSION(Ljava/lang/String;)V
//invoke-static 用于调用 static 方法(该方法始终被视为直接方法)。
invoke-interface {v0}, Ljava/lang/Runnable;->run()V
//invoke-interface 用于调用 interface 方法,也就是说,在具体类未知的对象上,使用引用 interface 的 method_id。
invoke-super {p0}, Ljava/lang/Object;->toString()Ljava/lang/String;
move-result-object v0
//invoke-super 来调用在该接口上定义的该方法的最具体、未被覆盖版
9、常用语句
//日志输出
const-string v2, "push"
.local v2, "tag":Ljava/lang/String;
invoke-static {v2, p1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
10、smali 文件结构
// 当前类名:.class public Lcom/kwai/game/ddz/MainActivity;
// 父类:.super Lcom/unity3d/player/UnityPlayerActivity;
// 文件名:.source "MainActivity.java"
# static fields
//静态字段 finish 会赋值、其他则只声明
# instance fields
//实例字段
# direct methods
.method static constructor <clinit>()V
//静态构造函数<静态代码块><静态初始化>
.method public constructor <init>()V
//实例构造函数
//其他方法
# virtual methods