zoukankan      html  css  js  c++  java
  • Smali语法

    最近一周在研究rom移植,所以就对Smali语言学习了一下,Smali语言其实就是Davlik的寄存器语言;Smali语言就是android的应用程序.apk通过apktool反编译出来的都有一个smali文件夹,里面都是以.smali结尾的文件,文件的展示语言。

    转载请标明出处:http://blog.csdn.net/wdaming1986/article/details/8299996

           如图,下面是HelloWorldApp通过apktool反编译出来的目录:

                   

                   Smali文件夹里面的目录,

                    

                  先打开一个主类HelloWorldAppActivity.smali文件,先来浏览一下里面的语言,在来说说smali的语法规则:

    1. .class public Lcom/cn/daming/activity/HelloWorldAppActivity;  
    2. .super Landroid/app/Activity;  
    3. .source "HelloWorldAppActivity.java"  
    4.   
    5.   
    6. # instance fields  
    7. .field private mTextView:Landroid/widget/TextView;  
    8.   
    9.   
    10. # direct methods  
    11. .method public constructor <init>()V  
    12.     .locals 0  
    13.   
    14.     .prologue  
    15.     .line 7  
    16.     invoke-direct {p0}, Landroid/app/Activity;-><init>()V  
    17.   
    18.     return-void  
    19. .end method  
    20.   
    21.   
    22. # virtual methods  
    23. .method public onCreate(Landroid/os/Bundle;)V  
    24.     .locals 2  
    25.     .parameter "savedInstanceState"  
    26.   
    27.     .prologue  
    28.     .line 12  
    29.     invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V  
    30.   
    31.     .line 13  
    32.     const/high16 v0, 0x7f03  
    33.   
    34.     invoke-virtual {p0, v0}, Lcom/cn/daming/activity/HelloWorldAppActivity;->setContentView(I)V  
    35.   
    36.     .line 14  
    37.     const/high16 v0, 0x7f05  
    38.   
    39.     invoke-virtual {p0, v0}, Lcom/cn/daming/activity/HelloWorldAppActivity;->findViewById(I)Landroid/view/View;  
    40.   
    41.     move-result-object v0  
    42.   
    43.     check-cast v0, Landroid/widget/TextView;  
    44.   
    45.     iput-object v0, p0, Lcom/cn/daming/activity/HelloWorldAppActivity;->mTextView:Landroid/widget/TextView;  
    46.   
    47.     .line 15  
    48.     iget-object v0, p0, Lcom/cn/daming/activity/HelloWorldAppActivity;->mTextView:Landroid/widget/TextView;  
    49.   
    50.     const/high16 v1, 0x7f04  
    51.   
    52.     invoke-virtual {v0, v1}, Landroid/widget/TextView;->setText(I)V  
    53.   
    54.     .line 16  
    55.     return-void  
    56. .end method  

    上面的smali语言对应的java类就是HelloWorldAppActivity.java类如下:

    1. package com.cn.daming.activity;  
    2.   
    3. import android.app.Activity;  
    4. import android.os.Bundle;  
    5. import android.widget.TextView;  
    6.   
    7. public class HelloWorldAppActivity extends Activity {  
    8.     private TextView mTextView;  
    9.     /** Called when the activity is first created. */  
    10.     @Override  
    11.     public void onCreate(Bundle savedInstanceState) {  
    12.         super.onCreate(savedInstanceState);  
    13.         setContentView(R.layout.main);  
    14.         mTextView = (TextView)findViewById(R.id.text_view);  
    15.         mTextView.setText(R.string.hello);  
    16.     }  
    17. }  


            通过对比发现基本的方法名称没有改变,多了一个.method public constructor <init>()V表示该类的不带参数缺省的构造方法,onCreate()方法是以.method public onCreate(Landroid/os/Bundle;)V开始,.end method结束;方法的表示形式就是这个样子的,就像赵本山说小品一样:“就算你穿上马甲,我也认识你”;哈哈。


           下面介绍一下Smali代码注入,原理:在已有APK或JAR包中插入一些Dalvik虚拟机的指令,从而改变原有程序的路径和行为。例如把上面的HelloWorldAppActivity的mTextView.setText(R.string.hello);修改一个字符串“This is daming change the smali programmer”替换原代码的R.string.hello;

    只需要修改HelloWorldAppActivity.smali文件的50,51,52行就可以了,

    1. const/high16 v1, 0x7f04  
    2.   
    3. invoke-virtual {v0, v1}, Landroid/widget/TextView;->setText(I)V  

    修改为

    1. const-string v1, "This is daming change the smali programmer"  
    2.   
    3. invoke-virtual {v0, v1}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V  

    再通过apktool  b  需要打包回去的文件

    打包回去就在反编译后的HelloWorldApp文件里生成一个dist文件夹,里面就有打包的HelloWorldApp.apk。如图

          

           注意:要直接安装到手机或模拟器是不行的,需要签名,可以通过APKSign_gr这个签名软件来签名,也可以通过其他方式签名,在签名的时候如果一开始在eclipse里运行生成的apk是使用了ADB的debug权限签名,如果使用APKSign_gr这个签名,需要在手机或模拟器中把原来的apk卸载掉,在安装新的apk,就ok了,这个是解决安装apk时“INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES”这个错误的。

    效果图如下:

                                      修改前                                             修改后

             


    Smali语法简单介绍如下

           Davlik字节码中,寄存器都是32位的,能够支持任何类型,64位类型(Long/Double)用2个寄存器表示;

           Dalvik字节码有两种类型:原始类型;引用类型(包括对象和数组)

                  原始类型v   void  只能用于返回值类型

                                    Z   boolean

                                    B   byte

                                    S   short

                                    C   char

                                     I    int

                                    J    long(64位)

                                    F   float

                                    D   double(64位)

                  对象类型Lpackage/name/ObjectName;  相当于java中的package.name.ObjectName;解释如下:

                                     L:表示这是一个对象类型

                                     package/name:该对象所在的包

                                     ;:表示对象名称的结束

                  数组的表示形式:

                                      [I  :表示一个整形的一维数组,相当于java的int[];

                                      对于多维数组,只要增加就行了,[[I = int[][];注:每一维最多255个; 

                   对象数组的表示形式:

                                       [Ljava/lang/String    表示一个String的对象数组;

      

                   方法的表示形式:

                                       Lpackage/name/ObjectName;——>methodName(III)Z  详解如下:

                                       Lpackage/name/ObjectName  表示类型

                                       methodName   表示方法名

                                       III   表示参数(这里表示为3个整型参数)

                                       说明:方法的参数是一个接一个的,中间没有隔开;

                    

                     字段的表示形式:

                                        Lpackage/name/ObjectName;——>FieldName:Ljava/lang/String;

                                        即表示: 包名,字段名和各字段类型

     

                      有两种方式指定一个方法中有多少寄存器是可用的:

                                         .registers  指令指定了方法中寄存器的总数

                                         .locals        指令表明了方法中非参寄存器的总数,出现在方法中的第一行

     

            方法的传参:

                    当一个方法被调用的时候,方法的参数被置于最后N个寄存器中;

                              例如,一个方法有2个参数,5个寄存器(v0~v4)

                                          那么,参数将置于最后2个寄存器(v3和v4)

                     非静态方法中的第一个参数总是调用该方法的对象;

                     说明:对于静态方法除了没有隐含的this参数外,其他都一样

              寄存器的命名方式:

                      V命名

                      P命名  第一个寄存器就是方法中的第一个参数寄存器

                      比较:使用P命名是为了防止以后如果在方法中增加寄存器,需要对参数寄存器重新进行编号的缺点

                      特别说明一下:Long和Double类型是64位的,需要2个寄存器

                               例如:对于非静态方法

                                           LMyObject——>myMethod(IJZ)V;

                                           有4个参数:LMyObject,int,long,bool;   需要5个寄存器来存储参数;

                                                                P0    this

                                                                P1    I (int)

                                                                P2,P3  J (long)

                                                                P4    Z(bool)

    好了,今天就说总结整理这么多吧,以后有时间再整理一翻!希望对大家有帮助;

    参考资料如下:

    MIUI ROM适配之旅第四天——移植MIUI Framework:http://www.miui.com/thread-409543-1-1.html

                                        smali语法:http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html

                                                                Smali代码注入:http://blog.sina.com.cn/s/blog_5674d18801019i89.html

                                                                     SMALI语法:http://bbs.pediy.com/showthread.php?t=151769

  • 相关阅读:
    HDU4507 吉哥系列故事――恨7不成妻(数位dp)
    UCF Local Programming Contest 2017 G题(dp)
    ICPC Latin American Regional Contests 2019 I题
    UCF Local Programming Contest 2017 H题(区间dp)
    HDU2089 不要62
    AcWing1084 数字游戏II(数位dp)
    UCF Local Programming Contest 2017 F题(最短路)
    Google Code Jam 2019 Round 1A Pylons(爆搜+贪心)
    AcWing1083 Windy数(数位dp)
    Vue
  • 原文地址:https://www.cnblogs.com/lvcha/p/3301252.html
Copyright © 2011-2022 走看看