美文网首页
4.smali语法学习笔记

4.smali语法学习笔记

作者: 普通的程序员 | 来源:发表于2017-12-03 15:16 被阅读0次

    smali语言还是相对纯机器码来说,比较容易理解的
    --但最好是结合工具一起学--
    --还可以参考其他的整理文章--

    先来一个最简单的模型类


    simpeModel.java

    对应的smali


    simpleModel.smali

    (表格只是简单做一个映射关系的整理)

    java smali description
    package .class 包名
    extends .super 父类名
    class .source 类名
    params .field 定义字段
    int I int类型
    Integer Ljava/lang/Integer Integer类型
    引用类型 Lxx/xx/xx 该引用类型的完整包名
    boolean Z 布尔值
    byte B 字节
    short S 短整型
    char C 字符
    long J 长整型
    float F 浮点数
    double D 浮点数
    void V
    数组类型 [ 数组
    function .method 定义方法
    constructor 构造器方法
    .prologue 开始了
    .registers 申请寄存器的个数,貌似不用关心这个
    .line x 对应源java文件行数
    两个简单的方法 image.png

    func1括号里有Lxx/xx/xx说明有形参,形参类型是String,也有返回值,返回值类型也是String
    .param 指名 形参名 value
    .prologue以下开始正式的代码逻辑
    .line 38 ,源码38行的代码
    return-object 返回该对象的引用,其实就是把p0里的值返回来。

    func2无形参,返回值类型String
    const-string 声明了一个String 类型的变量 ,值是 "abcdefg"
    .local 说是 指定了使用的局部变量的个数,我这里简单的认为,就是把v0给了一个局部变量 func2string

    简单的if-else判断 fun3的smali

    没想到这么长。
    这里有点绕,根据


    跳转指令 if-else跳转指令

    当vB为0的时候


    image.png

    则直接翻译smali为

    L93-int类型形参num,放到寄存器p1
    
    L96~L97-源码47行,如果p1的值小于等于0,跳到cond_3
    
    L99~L102-源码49行,结束local寄存器p1,跳到goto_2,
    返回p1的值
    
    L104~L109-源码48行,重开寄存器p1,cond_3 入口
    如果p1的值 不等于0,跳到cond_7
    否则(也就是p1等于0)把 0x0这个值给p1,然后跳到goto_2
    
    L113~L115 -也就是源码49行,cond_7入口,
    neg-int对第一个p1进行求补,然后把值给第二个p1
    
    L117~L118 -goto_2入口,end_method
    

    是不是感觉和java代码func3看起来不一样?
    我给自己的解释是类似java内存模型发生了重排序的优化,也不知道对不对,有大神知道的话评论区求解答。
    不过回过头来再看这个smali,
    顺序上虽然和源码顺序并不一致,但是按照直接翻译的意思去写java代码

    if( p1 <= 0){
        if(p1 != 0)return -p1
        else return 0
    } else return p1
    

    结果是一样的。

    再来一个


    image.png image.png

    有了func3的翻译经验
    func4就很好翻译了
    if-eqz p1,也就是形参num p1等于0的话,直接到cond_3,赋值0,最后返回。
    其余的直接返回p1

    if(p1 == 0)return 0
    else return p1
    

    这个优化感觉更能说服自己了,==操作比!=操作更简单

    来一个switch跳转


    switch
    太长了

    L145~L146-源码59行,拿p1做switch(packed-switch关键字)偏移区pswitch_data_a
    要看到底部
    L174~L179-实际上只有两个case需要做判断 pswitch-6和pswitch-8(也就是两个偏移区)
    L156~L163-pswitch_6,把0x0给v0,跳到goto_5
    L165~L172-pswitch_8,把0x1给v0,跳到goto_5
    L151~L154-goto_5入口把int型的本地(.local关键字)参数result指向寄存器v0,返回v0
    其余的 把0x29a给v0

    int result;
    switch(p1){
      case pswitch_6:
              result = 0;
              break;
      case pswitch_8:
              result = 1;
              break;
      default:
              result = 0x29a;
              break;
    }
    return result;
    

    相当于帮我优化了case -1,因为case -1和default都是同样的处理方法


    常用的加log打印信息的方法


    image.png System.out.println("sout"); Log.d("log", func2())

    那加入在有些情况下,调用Log.d,该类并没有引入
    android.util.Log包怎么办?


    通过完整的包名调用 我发誓这两种写法,smali编译出来是一样的

    放一个四哥的自定义代码添加方案
    以上笔记,仅供参考。

    相关文章

      网友评论

          本文标题:4.smali语法学习笔记

          本文链接:https://www.haomeiwen.com/subject/eusomxtx.html