• smali 语言语法


    Androidkiller 可以反编译Android的apk,生成一种.smali代码。(这理解好像不对)

    网上找了一篇smali的语法手册,可以方便查找,文章名《Smali文件语法参考》

    手册地址:http://blog.csdn.net/litton_van/article/details/7843490

    网上有一篇smali的语法讲解(java与smali对照讲解,推荐+赞),地址:http://blog.csdn.net/hp910315/article/details/51823236

    下面是网上找的一篇关于smali的语法的简单介绍:

    文章来源:http://www.brogrammer.cn/android/smali/

    1.smali

    apk文件通过apktool反编译出来的都有一个smali文件夹,里面都是以.smali结尾的文件。
    smali语言是Davlik的寄存器语言,语法上和汇编语言相似,Dalvik VM与JVM的最大的区别之一就是Dalvik VM是基于寄存器的。基于寄存器的意思是,在smali里的所有操作都必须经过寄存器来进行。

    2.基本数据类型

    B—byte
    C—char
    D—double
    F—float
    I—int
    S—short
    V—void
    J—long
    Z—boolean

    注意J、Z两个不是对应类型的首字母;
    在dalvik字节码中,寄存器都是32位的,能够支持任何类型,Long和Double类型是64位的,需要2个寄存器;
    V 只能用于返回值类型;

    3.数组和对象是引用类型

    数组的表示方式是在基本类型前加上前中括号“[”,例如int数组和float数组分别表示为:[I、[F;
    对象类型以L作为开头来表示,格式是Lpackage/ClassName;(用分号表示对象结束是必须的),示例:
    String对象在smali中为:Ljava/lang/String;
    Class1对象的一个boolean成员表示为:Lcom/disney/Class1;->isRunning:Z
    Class1对象的一个String对象成员表示为:Lcom/disney/Class1;->name:Ljava/lang/String;
    可以总结为格式为对象类型->成员名:成员类型,->表示所属关系,类型尾部必须包括一个分号。
    内部类表示为:Lpackage/ClassName$innerObjectName;,也就是在内部类前加“$”符号

    4.函数

    格式:Func-Name (Para-Type1Para-Type2Para-Type3…)Return-Type

    返回类型在最后,参数之间没有任何分隔符,示例:

    void fun()
    fun()V
    
    boolean fun(int, int, int)
    fun(III)Z
    
    String fun(boolean, int[], int[], String, long)
    fun(Z[I[ILjava/lang/String;J)Ljava/lang/String;

    5.语法

    #标记,构造函数的返回类型为V,名字为<init>

    # static fields        定义静态变量的标记
    # instance fields      定义实例变量的标记
    # direct methods       定义静态方法的标记??
    # virtual methods      定义非静态方法的标记??
     .class public Lcom/disney/WMW/WMWActivity;
     .super Lcom/disney/common/BaseActivity;
     .source "WMWActivity.java"
     .implements Lcom/burstly/lib/ui/IBurstlyAdListener;

    上面这几行代码表示类名,父类名,源文件名,实现了接口。

    .annotation
     内部类
    .end annotation

    6.局部变量

    本地寄存器(local register,非参寄存器)用v开头数字结尾的符号来表示,如v0、v1、v2、…,
    参数寄存器(parameter register)用p开头数字结尾的符号来表示,如p0、p1、p2、…,
    .registers 用来标明方法中寄存器的总数,即参数寄存器和非参寄存器的总数。
    .local 0,标明在这个函数中最少要用到的本地寄存器的个数,出现在方法中的第一行。在这里,由于只需要调用一个父类的onDestroy()处理,所以只需要用到p0,所以使用到的本地寄存器数为0,在植入代码后不要忘记可能要修改.local的值。
    如 .local 4,则可以使用的寄存器是v0-v3。
    当一个方法被调用的时候,方法的参数被置于最后N个寄存器中。
    在实例函数中,p0代指“this”,p1表示函数的第一个参数,p2代表函数中的第二个参数…,
    在static函数中,p1表示函数的第一个参数,p2代表函数中的第二个参数…,因为Java的static方法中没有this方法。
    示例:

    const/4 v0, 0x0
    iput-boolean v0, p0, Lcom/disney/Class1;->isRunning:Z

    上面第一句中把值0x0存到v0本地寄存器中,
    第二句用iput-boolean指令把v0中的值存放到this.isRunning这个成员变量中,即this.isRunning = false; 因为在实例函数中p0代表的是“this”,Lcom/disney/Class1;是类名,对应实例是p0。

    7.成员变量和指令

    # static fields
    .field private static final PREFS_INSTALLATION_ID java/lang/String; = "installationId"
    # instance fields
    .field private _activityPackageName java/lang/String;

    获取和操作静态成员变量和实例成员变量有不同的指令。
    读取的指令有:iget、sget、iget-boolean、sget-boolean、iget-object、sget-object等,
    赋值的指令有:iput、sput、iput-boolean、sput-boolean、iput-object、sput-object等。
    带“-object”表示操作的成员变量是对象类型,没有“-object”后缀的表示操作的成员变量对象是基本数据类型,特别地boolean类型则使用带“-boolean”的指令操作。

    获取static fields的指令示例:

    sget-object v0, Lcom/disney/Class1;->PREFS_INSTALLATION_ID:Ljava/lang/String;

    上句中sget-object指令把PREFS_INSTALLATION_ID这个String成员变量获取并放到v0寄存器中。

    获取instance fields的指令与static fields的类似,需要指明对象所属的实例。示例:

    iget-object v0, p0, Lcom/disney/Class1;->_view:Lcom/disney/Class2;

    上句iget-object指令比sget-object多了一个参数p0,就是该变量所在类的实例,在这里就是p0即“this”。

    put指令的使用和get指令是统一的,示例:

    const/4 v3, 0x0
    sput-object v3, Lcom/disney/Class1;->globalIapHandler:Lcom/disney/config/GlobalPurchaseHandler;

    上句相当于Class1.globalIapHandler = null;

    8.函数调用

    smali中的函数调用也分为direct和virtual两种类型,direct method就是private函数,public和protected函数都属于virtual method。在调用函数时,有invoke-direct,invoke-virtual,invoke-static、invoke-super以及invoke-interface等几种不同的指令。还有invoke-XXX/range 指令的,这是参数多于4个的时候调用的指令,比较少见。

    invoke-static:就是调用static函数的,示例:

    invoke-static {}, Lcom/disney/Class1;->fun()Z

    上句invoke-static后面有一对大括号“{}”,内部是调用该方法的实例和参数列表,由于这是static方法也不需要参数,所以{}内为空。

    invoke-super:调用父类方法,在onCreate、onDestroy等方法都能看到。
    invoke-direct:调用private函数,示例:

    invoke-direct {p0}, Lcom/disney/Class1;->getGlobalIapHandler()Lcom/disney/config/GlobalPurchaseHandler;

    上句即this->getGlobalIapHandler(),函数GlobalPurchaseHandler getGlobalIapHandler()是定义在Class1中的一个private函数。

    invoke-virtual:用于调用protected或public函数,示例:

    sget-object v0, Lcom/disney/Class1;->shareHandler:Landroid/os/Handler;
    invoke-virtual {v0, v3}, Landroid/os/Handler;->removeCallbacksAndMessages(Ljava/lang/Object;)V

    上句v0是shareHandler android/os/Handler,v3是传递给removeCallbackAndMessage方法的Ljava/lang/Object参数。

    9.获取函数调用结果

    在smali里调用函数和返回函数结果需要分开来完成,在调用的函数返回非void后,用move-result(返回基本数据类型)和move-result-object(返回对象)指令获取返回结果。

    示例:

    const/4 v2, 0x0
    invoke-virtual {p0, v2}, Lcom/disney/Class1;->getPreferences(I)Landroid/content/SharedPreferences;
    move-result-object v1

    上句v1保存的就是调用this.getPreferences(int)方法返回的SharedPreferences实例。

    10.函数体

    .method   和  .end method之间。

    示例:

    .method protected onDestroy()V
    .locals 0
    
    .prologue
    .line 277
    invoke-super {p0}, Lcom/disney/common/BaseActivity;->onDestroy()V
    
    .line 279
    return-void
    .end method

    上段是onDestroy()函数。
    .line 277,标注了该代码在原Java文件中的行数,它不是必须的,去掉没有编译问题。它在出错时可以指出错误位置,jd-gui工具即是通过分析这些信息将smali代码还原成Java代码的。

    11.条件语法

    if-eq p1, v0, :cond_8 
        :cond_8
        invoke-direct {p0}, Lcom/paul/test/a;->d()V

    上段表示如果p1和v0相等,则执行cond_8的流程:调用com.paul.test.a的d()方法

    if-ne p1, v0, :cond_b 
        :cond_b
        const/4 v0, 0x0
        invoke-virtual {p0, v0}, Lcom/paul/test/a;->setPressed(Z)V
        invoke-super {p0, p1, p2}, Landroid/view/View;->onKeyUp(ILandroid/view/KeyEvent;)Z
        move-result v0

    上段表示不相等则执行cond_b的流程。

  • 相关阅读:
    326周日去找书
    新视野大学英语-Book1
    预编译头文件来自编译器的早期版本,或者预编译头为 C++ 而在 C 中使用它(或相反)
    自定义GRUB主题
    Linux安装CMake
    Linux编译安装Apache
    @Scheduled注解
    熵权可拓物元模型
    Linux更新Python3.8
    Linux下更新GCC
  • 原文地址:https://www.cnblogs.com/pursuitofacm/p/6736830.html
Copyright © 2020-2023  润新知