smali的语法结构和实际应用

smali是Dalvik的寄存器语言,smali代码是dex反编译而来的。

一:关键字

名称注释
.class类名
.super父类名,继承的上级类名名称
.source源名
.field变量
.method方法名
.register寄存器
.end method方法名的结束
public公有
protected半公开,只有同一家人才能用
private私有,只能自己使用
.parameter方法参数
.prologue方法开始
.line xxx位于第xxx行

二:数据类型对应

Smali类型Java类型注释
Vvoid无返回值
Zboolean布尔值类型,返回0或1
Bbyte字节类型,返回字节
Sshort短整数类型,返回数字
Cchar字符类型,返回字符
Iint整数类型,返回数字
Jlong (64位 需要2个寄存器存储)长整数类型,返回数字
Ffloat单浮点类型,返回数字
Ddouble (64位 需要2个寄存器存储)双浮点类型,返回数字
stringString文本类型,返回字符串
Lxxx/xxx/xxxobject对象类型,返回对象

三:常用指令

关键字注释
const重写整数属性,真假属性内容,只能是数字类型
const-string重写字符串内容
const-wide重写长整数类型,多用于修改到期时间
return返回指令
if-eq全称equal(a=b),比较寄存器ab内容,相同则跳
if-ne全称not equal(a!=b),ab内容不相同则跳
if-eqz全称equal zero(a=0),z即是0的标记,a等于0则跳
if-nez全称not equal zero(a!=0),a不等于0则跳
if-ge全称greater equal(a>=b),a大于或等于则跳
if-le全称little equal(a<=b),a小于或等于则跳
goto强制跳到指定位置
switch分支跳转,一般会有多个分支线,并根据指令跳转到适当位置
iget获取寄存器数据

四:其余指令可用语法工具查询

//一个私有、静态、不可变的方法   方法名
.method private static final onCreate$lambda-2(Lkotlin/jvm/internal/Ref$IntRef;Lcom/zj/wuaipojie/ui/ChallengeSecond;Landroid/widget/ImageView;Landroid/widget/ImageView;Landroid/widget/ImageView;Landroid/view/View;)Z //(这里面是方法的参数)这里是方法返回值类型,表示布尔值类型,返回假或真
    .registers 7  //寄存器数量
 
    .line 33  //代码所在的行数
    iget p0, p0, Lkotlin/jvm/internal/Ref$IntRef;->element:I  //读取p0(第一个参数,参考寄存器知识)中element的值赋值给p0
 
    const/4 p5, 0x1  //p5赋值1
 
    const/16 v0, 0xa //v0赋值10,在16进制里a表示10
 
    if-ge p0, v0, :cond_15  //判断p0的值是否大于或等于v0的值(即p0的值是否大于或等于10),如果大于或等于则跳转到:cond_15
 
    .line 34  //以下是常见的Toast弹窗代码
    check-cast p1, Landroid/content/Context; //检查Context对象引用
 
    const-string p0, "请先获取10个硬币哦" //弹窗文本信息,把""里的字符串数据赋值给p0
 
    check-cast p0, Ljava/lang/CharSequence; //检查CharSequence对象引用
 
    invoke-static {p1, p0, p5}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast; 
    //将弹窗文本、显示时间等信息传给p1
 
    move-result-object p0  //结果传递给p0
 
    invoke-virtual {p0}, Landroid/widget/Toast;->show()V  //当看到这个Toast;->show你就应该反应过来这里是弹窗代码
 
    goto :goto_31  //跳转到:goto_31
 
    :cond_15 //跳转的一个地址
 
    invoke-virtual {p1}, Lcom/zj/wuaipojie/ui/ChallengeSecond;->isvip()Z  //判断isvip方法的返回值是否为真(即结果是否为1)
 
    move-result p0  //结果赋值给p0
 
    if-eqz p0, :cond_43 //如果结果为0则跳转cond_43地址
 
    const p0, 0x7f0d0018  //在arsc中的id索引,这个值可以进行查询
 
    .line 37
    invoke-virtual {p2, p0}, Landroid/widget/ImageView;->setImageResource(I)V //设置图片资源
 
    const p0, 0x7f0d0008
 
    .line 38
    invoke-virtual {p3, p0}, Landroid/widget/ImageView;->setImageResource(I)V
 
    const p0, 0x7f0d000a
 
    .line 39
    invoke-virtual {p4, p0}, Landroid/widget/ImageView;->setImageResource(I)V
 
    .line 40
    sget-object p0, Lcom/zj/wuaipojie/util/SPUtils;->INSTANCE:Lcom/zj/wuaipojie/util/SPUtils; 
 
    check-cast p1, Landroid/content/Context;
 
    const/4 p2, 0x2 //p2赋值2
 
    const-string p3, "level" //sp的索引
 
    invoke-virtual {p0, p1, p3, p2}, Lcom/zj/wuaipojie/util/SPUtils;->saveInt(Landroid/content/Context;Ljava/lang/String;I)V //写入数据
 
    goto :goto_50 //跳转地址
 
    :cond_43
 
    check-cast p1, Landroid/content/Context;
 
    const-string p0, "\u8bf7\u5148\u5145\u503c\u5927\u4f1a\u5458\u54e6\uff01" //请先充值大会员哦!
 
    check-cast p0, Ljava/lang/CharSequence;
 
    invoke-static {p1, p0, p5}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
 
    move-result-object p0
 
    invoke-virtual {p0}, Landroid/widget/Toast;->show()V
 
    :goto_50
    return p5  //返回p5的值
.end method //方法结束
 
//判断是否是大会员的方法
.method public final isvip()Z
    .registers 2
 
    const/4 v0, 0x0 //v0赋值0
 
    return v0 //返回v0的值
 
.end method

五:寄存器

在smali里的所有操作都必须经过寄存器来进行:本地寄存器用v开头数字结尾的符号来表示,如v0、 v1、v2。 参数寄存器则使用p开头数字结尾的符号来表示,如p0、p1、p2。特别注意的是,p0不一定是函数中的第一个参数,在非static函数中,p0代指“this”,p1表示函数的第一个 参数,p2代表函数中的第二个参数。而在static函数中p0才对应第一个参数(因为Java的static方法中没有this方法)

条件判定

  • if-eq vA, vB, :cond_** 如果vA等于vB则跳转到:cond_**
  • if-ne vA, vB, :cond_** 如果vA不等于vB则跳转到:cond_**
  • if-lt vA, vB, :cond_** 如果vA小于vB则跳转到:cond_**
  • if-ge vA, vB, :cond_** 如果vA大于等于vB则跳转到:cond_**
  • if-gt vA, vB, :cond_** 如果vA大于vB则跳转到:cond_**
  • if-le vA, vB, :cond_** 如果vA小于等于vB则跳转到:cond_**
  • if-eqz vA, :cond_** 如果vA等于0则跳转到:cond_**
  • if-nez vA, :cond_** 如果vA不等于0则跳转到:cond_**
  • if-ltz vA, :cond_** 如果vA小于0则跳转到:cond_**
  • if-gez vA, :cond_** 如果vA大于等于0则跳转到:cond_**
  • if-gtz vA, :cond_** 如果vA大于0则跳转到:cond_**
  • if-lez vA, :cond_** 如果vA小于等于0则跳转到:cond_**
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
© 版权声明
THE END
喜欢就支持一下吧
点赞5赞赏 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容