smali语法部分已经完结,感兴趣的可以访问下面这个链接阅读下一部分:安卓逆向入门——smali语法(下)_不会算法的小白的博客-CSDN博客
smali和Java基本数据类型对比
smali | java |
B | byte |
S | short |
I | int |
J | long |
F | float |
D | double |
C | char |
Z | boolean |
V | void |
[ | 数组 |
L+全类名路径用/分割 | object |
注释
使用`#`表示
类声明
.class + 权限修饰符 + 类名; # 以分号结尾
比如如下Java代码:
public class Test implements CharSequence{
}
使用smali代码表示为:
.class public LTest; # 声明类 (必须)
.super Ljava/lang/Object; # 声明父类 默认继承Object (必须)
.implements Ljava/lang/CharSequence; # 如果实现了接口 则添加接口代码
.source "Test.java" # 源码文件 (非必须)
关于分号:
凡是L开头全包名路径结尾都需要加分号
字段声明(成员/全局变量)
.field+权限修饰符+静态修饰符 + 变量名:变量全类名路径;
比如以下Java代码:
public class Test{
private static String a;
}
用smali代码表示为:
.class public LTest; # 声明类 (必须)
.super Ljava/lang/Object; # 声明父类 默认继承Object (必须)
.source "Test.java" # 源码文件 (非必须)
# 如果是非静态,将static去掉即可
.field private static a:Ljava/lang/String;
常量声明
.field 权限修饰符 + 静态修饰符 + final + 变量名:变量全类名路径; = 常量值
比如以下Java代码:
public class Test{
private static final String a = "Hello World";
}
用smali代码表示为:
.class public LTest;
.super Ljava/lang/Object;
.field private static final a:Ljava/lang/String; = "Hello World"
成员方法/函数声明:
.method 权限修饰符 + 静态修饰符 + 方法名(参数类型)返回值类型
#方法体
.end method # 方法结尾标志
无参无返回值类型:
public class Test{
public static void getName(){
}
}
用smali代码表示为:
.class public LTest;
.super Ljava/lang/Object;
.method public static getName()V
return-void
.end method
带参并且带有返回值的方法:
比如以下Java代码:
public String getName(String p){
return "hello";
}
用smali代码表示为:
.method public getName(Ljava/lang/String;)Ljava/lang/String;
const-String v0, "hello"
return-object v0
.end method
关于方法返回关键字
主要有以下四种
return-void
return-object
return
return-wide
数据类型对应关系表如下:
smali方法返回关键字 | java数据类型 |
return | byte |
return | short |
return | int |
return-wide | long |
return | float |
return-wide | double |
return | char |
return | boolean |
return-void | void |
return-object | 数组 |
return-object | object |
构造方法/构造函数声明
.method 权限修饰符 + constructor <init>(参数类型)返回值类型
#方法体
.end method
#构造方法返回值固定是void
比如以下Java代码:
public class Test{
public Test(String a){
}
}
用smali代码表示为:
.class public LTest;
.super Ljava/lang/Object; # 声明父类
.method public constructor <init>(Ljava/lang/String;)V
invoke-direct {p0}, Ljava/lang/Object;-><init>()V # 调用父类构造方法
return-void
.end method
静态代码块的声明
.method 权限修饰符 static constructor <clinit>()V
#方法体
.end method
比如以下Java代码:
public class Test{
static{
}
}
用smali代码表示为:
.class public LTest;
.super Ljava/lang/Object;
.method public static constructor <clinit>()V
return-void
.end method
方法调用
关键字
invoke-virtual # 用于非私有实例方法的调用
invoke-direct # 用于构造方法以及私有方法的调用
invoke-static # 调用静态方法
invoke-super # 调用父类的方法
invoke-interface # 调用接口方法
非私有实例方法的调用
invoke-virtual {参数}, 方法所属类名;->方法名(参数类型)返回值类型
比如以下Java代码:
public class Test{
public Test(String a){
getName();
}
public String getName(){
return "hello";
}
}
用smali代码表示为:
.class public LTest;
.super Ljava/lang/Object;
.method public constructor <init>(Ljava/lang/String;)V
invoke-direct {p0}, Ljava/lang/Object;-><init>()V # 调用父类构造方法
invoke-virtual {p0}, LTest;->getName()Ljava/lang/String; # 调用普通成员getName方法
# p0指的是Java中的this,表示当前对象
return-void
.end method
.method public getName()Ljava/lang/String;
const-string v0, "hello" # 定义局部字符串常量
return-object vo # 返回常量
.end method
私有方法以及构造方法的调用
invoke-direct {参数}, 方法所属类名;->方法名(参数类型)返回值类型
私有方法的调用
比如以下Java代码:
public class Test{
public Test(String a){
getName();
}
// 私有方法
private String getName(){
return "hello";
}
}
用smali代码表示为:
.class public LTest;
.super Ljava/lang/Object;
.method public constructor <init>(Ljava/lang/String;)V
invoke-direct {p0}, Ljava/lang/Object;-><init>()V # 调用父类构造方法
invoke-direct {p0}, LTest;->getName()Ljava/lang/String; # 调用私有实例方法
return-void
.end method
.method private getName()Ljava/lang/String;
const-string v0, "hello" # 定义局部字符串常量
return-object vo # 返回常量
.end method
构造方法的调用
比如以下Java代码:
public class Test{
public Test(String a){
new Test2("hello");
}
public class Test2{
public Test2(String a){
}
}
}
用smali代码表示为:
.class public LTest;
.super Ljava/lang/Object;
# 匿名内部类的声明
.annotation system Ldalvik/annotation/MemberClass;
value = {
LTest$Test2;
}
.end annotation
# 构造方法
.method public constructor <init>(Ljava/lang/String;)V
# 初始化父类构造方法
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
# 创建对象
new-instance vo, LTest$Test2;
# 定义常量
const-String v1, "hello"
# 调用构造方法
invoke-direct {v0, p0, v1}, LTest$Test2;-><init>(LTest;Ljava/lang/String;)v
return-void
.end method
静态方法的调用并获取返回值(不区分私有共有 静态优先)
invoke-static {参数}, 方法所属类名;->方法名(参数类型)返回值类型
比如以下Java代码:
public class Test{
public Test(String a){
String b = getName();
System.out.println(b);
}
private static String getName(){
return "hello";
}
}
用smali代码表示为:
.class public LTest;
.super Ljava/lang/Object;
.method public constructor <init>(Ljava/lang/String;)V
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
invoke-static {}, LTest;->getName()Ljava/lang/String;
move-result-object v0 # 将返回值赋给v0
return-void
.end method
.method private static getName()Ljava/lang/String;
const-string v0, "hello" # 定义局部字符串常量
return-object v0 # 返回常量
.end method
父类成员方法的调用
invoke-super {参数}, 方法所属类名;->方法名(参数类型)返回值类型
比如以下Java代码:
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
}
用smali代码表示为:
.method protected onCreate(Landroid/os/Bundle;)V
.registers 2
invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V
return-void
.end method
接口的调用
invoke-interface {参数}, 方法所属类名;->方法名(参数类型)返回值类型
比如以下Java代码:
public class Test{
private InterTest a = new Test2();
public Test(String a){
}
public void setAa(){
InterTest aa = a;
# 调用接口方法
aa.est2();
}
public class Test2 implements InterTest{
public Test2(){}
public void est2(){}
}
interface InterTest{
public void est2();
}
}
用smali代码表示为:
.class public LTest;
.super Ljava/lang/Object;
.method public constructor <init>(Ljava/lang/String;)V
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
# 声明setAa方法
.method public setAa()V
.registers 2
iget-object v0, p0, LTest;->a:LTest$InterTest;
# 调用接口方法
invoke-interface {v0}, LTest$InterTest;->est2()V
return-void
.end method