zoukankan      html  css  js  c++  java
  • 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的流程。

  • 相关阅读:
    How to build Linux system from kernel to UI layer
    Writing USB driver for Android
    Xposed Framework for Android 8.x Oreo is released (in beta)
    Linux Smartphone Operating Systems You Can Install Today
    Librem 5 Leads New Wave of Open Source Mobile Linux Contenders
    GUADEC: porting GNOME to Android
    Librem 5 – A Security and Privacy Focused Phone
    GNOME and KDE Join Librem 5 Linux Smartphone Party
    Purism计划推出安全开源的Linux Librem 5智能手机
    国产系统之殇:你知道的这些系统都是国外的
  • 原文地址:https://www.cnblogs.com/pursuitofacm/p/6736830.html
Copyright © 2011-2022 走看看