smali代码结构解析

一、开头(类的声明)

1、声明一个类继承自某个类

java代码如下

public class MainActivity extends AppCompatActivity 

对应的smali代码如下,解析见每行注释(smali注释使用#):

.class public Lcom/ylw/yhds/activity/MainActivity;#声明类,其中Lcom/ylw/yhds/activity/MainActivity;为类的全包名,L开头,分号结尾
.super Landroidx/appcompat/app/AppCompatActivity;#上一行类的父类,同样要用全包名
.source "MainActivity.java"#该smali文件源自MainActivity.java文件,此行可以不写
2、声明一个类继承某个接口

java代码如下

public class DataPackage implements Serializable

对应的smali代码如下,解析见每行注释(smali注释使用#),当没有继承具体的类时,使用Object类:

.class public Lcom/ylw/yhds/utils/DataPackage;#声明类,其中Lcom/ylw/yhds/utils/DataPackage;为类的全包名,L开头,分号结尾
.super Ljava/lang/Object;#上一行类的父类,同样要用全包名,当没有继承具体的类时,使用Object类
.source "DataPackage.java"#该smali文件源自DataPackage.java文件,此行可以不写

# interfaces#自动生成的注释
.implements Ljava/io/Serializable;#实现了Serializable接口,同样Ljava/io/Serializable;为全包名

二、方法的定义和调用

1、构造方法
  • 不论java代码中是否显式写成了构造方法,下面的构造方法代码都会生成
  • 私有方法和构造方法使用invoke-direct进行调用
  • 静态方法使用invoke-static进行调用
  • 平常自己写的一般方法使用invoke-virtual进行调用
  • # direct methods#自动生成的注释,表示以下内容为构造方法
    .method public constructor ()V#constructor 表示构造方法,V表示返回值为void
        .registers 1#.registers表示寄存器个数,可暂时理解为方法中变量的个数
    
        .prologue
        .line 6#从下一行开始到return-void结束,对应原java代码的第12行,方便对比阅读,此行可不写
        invoke-direct {p0}, Ljava/lang/Object;->()V#方法的调用,私有方法和构造方法使用invoke-direct进行调用
        #本行和以下注释不存在,为补充解释添加。{p0}对应java中向函数传递参数,这里smali的花括号类似于java中的小括号
        #p0对应constructor ()中小括号里的内容,可以理解为java中的this
        #Ljava/lang/Object;->()V表示要调用方法的所属类全包名路径和调用方法,即将参数p0传入到哪个类中的哪个方法
        #私有方法和构造方法调用格式整理如下
        #invoke-direct {参数}, 方法所属类的全包名路径->方法名称(方法参数签名)方法返回值签名
    
        return-void#对应constructor ()V中的V,即构造器的返回值为void
    .end method#与开头.method成对出现,可以理解为java中方法的花括号
    
    2、非构造方法(平时自己写的一些方法)
    2.1、无参返回值为String

    java代码如下

  • private static String getName(){
    	return "hello";
    }
    

    对应的smali代码如下,注意方法名与构造方法不同,无需constructor

  • .method private static getName()Ljava/lang/String;#由于java中String是一个对象,所以这里的返回值是String的全包名路径,而不是像void一样用V表示
    	.registers 1#.registers表示寄存器个数,可暂时理解为方法中变量的个数
    	
    	.line 22#对应原java代码的第22行,方便对比阅读,此行可不写
    	const-string v0,"hello"#声明一个常量字符串,将hello赋值给容器v0
    
    	return-object v0#返回v0容器中的内容,这里return-object与方法开头返回值为对象Ljava/lang/String;相对应
    .end method
    
    2.2、参数为String数组,返回值为空,方法内容为for循环

    java代码如下:

    public static void main(String[] args) {
        for (int i = 8; i < 3 ; i++) {
    
        }
    }
    
    smali代码如下:(重复内容注释见2.1),smali中以16进制表示数字
    .method public static main([Ljava/lang/String;)V
        .registers 3
        .param p0, "args"    # [Ljava/lang/String;
    
        .prologue
        .line 5#从此处.line到下一个.line即.line 8,中间的smali代码对应的是java的一行代码,即第5行for循环
        const/16 v0, 0x8#声明常量8,放到容器v0中
    
        .local v0, "i":I#表示v0这个容器中存放的值,在对应的java代码中对应的是变量i,可以不写
        :goto_2
        const/4 v1, 0x3#声明常量3,放到容器v1中
    
        if-ge v0, v1, :cond_8#if-ge表示如果大于等于,即如果v0>=v1,则跳转到:cond_8,执行return-void
    
    	#此行非自动生成,为补充解释添加。上面的if-ge不成立则顺序执行这些代码。
        add-int/lit8 v0, v0, 0x1#加法运算,v0=v0+0x1
    
        goto :goto_2#跳转到:goto_2
    
        .line 8
        :cond_8#跳转标识:cond_8
        return-void
    .end method
    

    三、其他示例

    smali代码

        new-instance v14, Ljava/lang/StringBuilder;#提前声明,我将要创建一个StringBuilder对象,用v14容器来装
    
        invoke-direct {v14}, Ljava/lang/StringBuilder;->()V#调用StringBuilder的构造方法创建StringBuilder对象,放到v14中
    

你可能感兴趣的:(开发语言,java)