smali汇编学习(1)

1.1smali语言基础语法-数据类型和描述符
smali里面有两种数据类型:

1).基本类型

在这里插入图片描述

2).引用类型------》1.对象类型,2.数组类型

对象类型表示形式: L 包名/对象名; L packagename/ObjectName;

packagename 使用”/“代替”.“

ObjectName是对象的名称;

分号表示对象的结束;

数组类型:

以 '['数据类型 加上类型描述符 的形式表示;

比如:

[ I 表示一维整型数组

[[ I 表示二维数组

[L java/lang/String 表示String数组

字段的描述

Davilk中对字段的描述分为两种,对基本类型字段的描述和对引用类型的描述,但是两者的描述格式一样:

对象类型类型描述符→字段名 : 类型描述符;

例如com.bluesson.Test类中存在String类型的name字段以及int类型的age字段,那么其描述为:

Lcom/bluesson/Test; →name:Ljava/lang/String;

Lcom/bluesson/Test;-→age:I

方法的描述

对象类型描述符-→方法名(参数类型描述符) 返回值类型描述符

下面以java.lang.String为例:

java方法: public char charAt(int index){… …}

Davilk描述: L java/lang/String; -→charAt(I) C

java方法: public void getChars(int srcBeg, int srcEnd ,char dst[],int dstBegin){…}

Davilk描述: L java/lang/String;-→getChars(I I [C I)V

java方法: public boolean equals(Object anObject){…}

Davilk描述:Ljava/lang/String;–→equals(L java/lang/Object;)Z

1.2 寄存器以及传参,局部变量
在smali汇编中,寄存器都是32位的,能够支持任何类型;64位类型(long和Double)用两个寄存器表示;

指定一个方法中有多少个寄存器有两个方法:

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

  2. locals 指令表明了方法中非参寄存器的数量;

方法中使用寄存器传参的默认规则:

1.当一个方法被调用的时候,方法的参数被设置于最后N个寄存器.如果一个方法有两个参数,5个寄存器(v0-v4),那么参数将置于最后两个寄存器v3和v4;

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

eg:LMyObject;-→callMe (II) V

这里有2个整型参数,另外还有一个隐含的LMyobject参数,所以总共有3个参数.如果该方法中指定了5个寄存器(v0-v4),以.registers方式指定5个或者以.local方式指定2个(2个local寄存器+3个参数寄存器)。当该方法被调用的时候,调用该方法的对象(this引用)存放在v2中,第一个整型参数存放于v3中,第二个整型参数存放于v4里面;

而静态方法除了没有隐含的this参数以外其他都一样;

寄存器的命名方式有两种:

1.V命名方式

2.P命名方式

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

下表表示了上个例子中的5个寄存器和3个参数的两种命名方法:

在这里插入图片描述
注意:baksmali默认对参数寄存器使用P命名方式;

下面看一个例子(java源码):

public void callMe(int a,int b){

System.out.println(a + b);

}

反编译之后的smali汇编代码:

.method  public callMe(II)V

             .locals 2              #定义局部变量寄存器,

             .param   p1 , "a"  # I 声明参数

             .param   p2 , "b"  #I

             .prologue             #代码起始处

             .line 20                 #源代码所在行数

 

#获取out对象

sget-object   v0, Ljava/lang/System;--→out:Ljava/io/PrintStream;

#out是属于 Ljava/lang/System类的;将out这个对象放于v0里面;

 

#将参数累加

add-int v1,p1,p2

#输出信息

invoke-virtual {v0,v1}, Ljava/io/PrintStream;→printIn(I)V

.Line 21

return-void

.end method

 

关于Long和Double值
Long和double类型是64位的,需要两个寄存器(切记)

对于非静态方法LMyobJect;-→MyMethod(IJZ)V,参数分别是LMyobject;,int,long,bool.故该方法至少需要5个寄存器来存储:

在这里插入图片描述

再看一个例子: (先看源码)

pubic void MyMethod(int a,long c,int b){

System.out.println(a+ c + b);

}

分析smali代码:


.method  public Mymethod(IJI)V

             .locals 6              #定义局部变量寄存器,总共v0,this,I,J(两个寄存器),Z

             .param   p1 , "a"  # I 声明参数

             .param   p2 , "c"  #J

            .param   p24, "b"  #I

 

             .prologue             #代码起始处

             .line 24                 #源代码所在行数

            sget-object v0,Ljava/lang/System;→out:Ljava/io/PrintStream;

           

         int-to-long v2,p1

        #v2 = v2+p2  v3 = v3+p3

       # int-to-long vx,  vy

       #转换Vy寄存器中的Int型值存入Vx,Vx+1,这里有两个寄存器

       add-long/2addr v2,p2

 

     int-to-long v4,p4

        #v2 = v2+v4  v3 = v3+v5

       add-long/2addr v2,v4

      .line 25

      return-void

.end method
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值