Smali语法
Smali语法
概述
- Android代码一般是用 java 编写的,执行 java 程序一般需要用到 java 虚拟机,在 Android 平台上也不例外,但是出于性能上的考虑,并没有使用标准的 JVM,而是使用专门的Android虚拟机(5.0以下为Dalvik,5.0以上为ART)。Android 虚拟机的可执行文件并不是普通的 class 文件,而是再重新整合打包后生成的 dex 文件。dex 文件反编译之后就是 Smali 代码,所以说,Smali 语言是 Android 虚拟机的反汇编语言。
- Dalvik VM是基于寄存器的,而JVM是基于栈的;Dalvik VM 比 JVM 速度更快,占用空间更少。
语法
数据类型
| Smail | Java | 备注 |
| v | void | |
| Z | boolean | |
| Z | boolean | |
| B | byte | |
| S | short | |
| C | char | |
| I | int | |
| J | long | |
| F | float | |
| D | double | |
| Lpackage/name; | 对象类型 | L表示这是一个对象类型,package表示该对象所在的包,;表示对象名称的结束 |
| [ | 数组类型 | [I表示一个int型数据,[Ljava/lang/String 表示一个String的对象数组 |
代码示例
- I:表示 int 类型.
- [[I: 表示 int[][] 数组.
- I: 表示 int 类型.
- Ljava/lang/String;: 表示 String 类型.
- [Ljava/lang/Object;: 表示对象数组 (Object[]).
- Ljava/lang/String;: 表示返回值是 String.
method(I[[IILjava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
# 对应 java 为:
String method(int,int[][],int,String,Object[])
寄存器命名规则
- p0, p1, …:方法参数寄存器.
- v0, v1, …:局部变量寄存器.
- 在非 static 方法中, p0 表示 this 对象, p1, p2, … 是方法的实际参数.
- 在 static 方法中, p0 是第一个参数, this 不存在.
| 寄存器 | 介绍 | 备注 |
| 参数寄存器(p0, p1, ...) |
①. 用于存储方法参数. ②. 在非 static 方法中, p0 表示 this 对象, p1, p2, ... 是方法的实际参数. ③. 在 static 方法中, p0 是第一个参数,this 不存在. |
①. 参数寄存器(p0、p1、…)由虚拟机根据方法签名自动分配,不计入 .locals 的 N. |
| 本地寄存器(v0, v1, ...) |
①. 用于存储方法内部的局部变量. |
①. .locals N: 声明本地寄存器数,参数寄存器的方法参数自动分配,不计入 N. ②. .registers M:声明参数寄存器和本地寄存器总数,等于参数寄存器数 + 本地寄存器数 |
非 static 方法
1. p0 是 this,即当前类的实例<br>
2. p1 是传入的 String 参数(未使用),对应函数签名里的 String 参数.<br>
3. v0 是本地寄存器, 用于存储 "Hello" 字符串
.method public showMessage(Ljava/lang/String;)V
.locals 1
const-string v0, "Hello"
invoke-virtual {p0, v0}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;)Landroid/widget/Toast;
return-void
.end method
static 方法
1. p0, p1 是两个 int 参数.<br>
2. v0 是本地寄存器,用于存储结果.<br>
3. add-int 是加法指令
.method public static add(II)I
.locals 1
add-int v0, p0, p1
return v0
.end method
# 对应的 java 为
public static int add(int a, int b) {
return a + b;
}
字节码指令
- 取值指令有:iget、sget、iget-boolean、sget-boolean、iget-object、sget-object 等.
- 赋值指令有:iput、sput、iput-boolean、sput-boolean、iput-object、sput-object 等.
方法表示
- 方法使用 .method 表示开始,使用 .end method 表示结束.
- Ljava/lang/String$xxx; 表示 xxx 是 String 类的内部类.
| 方法 | 含义 | 备注 |
| direct method |
①. 指的是 private 方法,static 方法,构造函数,类初始块 ②. 调用方式为 invoke-direct. |
①. 不能被子类重写. ②. 通常用于类内部逻辑,不涉及多态. |
| virtual method |
①.指的是public, protected, package-private 的实例方法 ②.调用方式为 invoke-virtual. |
①.可以被子类重写(支持多态). ②.支持动态绑定(运行时根据对象类型决定调用哪个方法). |
参考链接
1.Smali语法