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 <init>()V#constructor <init>表示构造方法,V表示返回值为void
        .registers 1#.registers表示寄存器个数,可暂时理解为方法中变量的个数
    
        .prologue
        .line 6#从下一行开始到return-void结束,对应原java代码的第12行,方便对比阅读,此行可不写
        invoke-direct {p0}, Ljava/lang/Object;-><init>()V#方法的调用,私有方法和构造方法使用invoke-direct进行调用
        #本行和以下注释不存在,为补充解释添加。{p0}对应java中向函数传递参数,这里smali的花括号类似于java中的小括号
        #p0对应constructor <init>()中小括号里的内容,可以理解为java中的this
        #Ljava/lang/Object;-><init>()V表示要调用方法的所属类全包名路径和调用方法,即将参数p0传入到哪个类中的哪个方法
        #私有方法和构造方法调用格式整理如下
        #invoke-direct {参数}, 方法所属类的全包名路径->方法名称(方法参数签名)方法返回值签名
    
        return-void#对应constructor <init>()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;-><init>()V#调用StringBuilder的构造方法创建StringBuilder对象,放到v14中
    

  • 22
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值