注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

熊猫正正的博客

熊猫正正的天空

 
 
 

日志

 
 

关于Smali语法的一些简单讲解和实例说明【一】  

2013-09-13 15:20:12|  分类: Android开发与逆 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
这一阵儿做rom,哦,不,应该说一直以来做rom,都在和smali打交道,smali的代码读起来相当费事,所以我一般都把dex反编译到java来对比着smali进行解读(但是有相当大一部分的dex是无法反编译到java的),但是这样也相当费事儿,google上有对于smali语法的详尽说明,不过是鸟文,而且看起来相当头疼。前两天偶然百度到关于smali的简略中文说明,作为smali专题的第一期,先转过来中文说明,第二期以后,写一些我修改smali的过程和理解。
 

dalvik字节码有两种类型,原始类型和引用类型。对象和数组是引用类型,其它都是原始类型。
V  void
,只能用于返回值类型
Z  boolean
B  byte
S  short
C  char
I  int
J  long
64位)
F  float
D  double(64
)
对象以Lpackage/name/ObjectName;的形式表示。前面的L表示这是一个对象类型,package/name/是该对象所在的包,ObjectName是对象的名字,“;”表示对象名称的结束。相当于java中的package.name.ObjectName。例如:Ljava/lang/String;相当于java.lang.String

数组的表示形式
?  [I——
表示一个整型一维数组,相当于java中的int[]
?  
对于多维数组,只要增加[就行了。[[I相当于int[][][[[I相当于int[][][]。注意每一维的最多255个。
?  
对象数组的表示:[Ljava/lang/String;表示一个String对象数组。
方法
表示形式:Lpackage/name/ObjectName;->MethodName(III)Z
?  Lpackage/name/ObjectName;
表示类型,MethodName是方法名。III为参数(在此是3个整型参数),Z是返回类型(bool型)。
?  
方法的参数是一个接一个的,中间没有隔开。
一个更复杂的例子:
method(I[[IILjava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
java中则为:
String method(int, int[][], int, String, Object[])
字段
表示形式:
Lpackage/name/ObjectName;->FieldName:Ljava/lang/String;
即包名,字段名和各字段类型。
寄存器
dalvik字节码中,寄存器都是32位的,能够支持任何类型。64位类型(LongDouble型)用2个寄存器表示。
有两种方式指定一个方法中有多少寄存器是可用的。.registers指令指定了方法中寄存器的总数。.locals指令表明了方法中非参寄存器的数量。
方法的传参
?  
当一个方法被调用的时候,方法的参数被置于最后N个寄存器中。如果一个方法有2个参数,5个寄存器(v0-v4),那么参数将置于最后2个寄存器——v3v4
?  
非静态方法中的第一个参数总是调用该方法的对象。
例如,非静态方法LMyObject;->callMe(II)V2个整型参数,另外还有一个隐含的LMyObject;参数,所以总共有3个参数。假如在该方法中指定了5个寄存器(v0-v4),以.registers方式指定5个或以.locals方式指定2个(即2local寄存器+3个参数寄存器)。当该方法被调用的时候,调用该方法的对象(即this引用)存放在v2中,第一个整型参数存放在v3中,第二个整型参数存放在v4中。
对于静态方法除了没有隐含的this参数外其它都一样。
寄存器的命名方式
有两种方式——V命名方式和P命名方式。P命名方式中的第一个寄存器就是方法中的第一个参数寄存器。在下表中我们用这两种命名方式来表示上一个例子中有5个寄存器和3个参数的方法。
v0    
第一个local register
v1    
第二个local register
v2  p0  
第一个parameter register
v3  p1  
第二个parameter register
v4  p2  
第三个parameter register
你可以用任何一种方式来引用参数寄存器——他们没有任何差别。
注意:baksmali默认对参数寄存器使用P命名方式。如果想使用V命名方式,可以使用-pl—no-parameter-registers选项。
使用P命名方式是为了防止以后如果要在方法中增加寄存器,需要对参数寄存器重新进行编号的缺点。
Long/Double

Long
double类型是64位的,需要2个寄存器(切记切记)。
例如,对于非静态方法LMyObject;->MyMethod(IJZ)V,参数分别是LMyObject;intlongbool。故该方法需要5个寄存器来存储参数。

p0  this
p1  I
p2,p3  J
p4  Z

 

补充:
# static fields             
定义静态变量的标记
# instance fields        
定义实例变量的标记
# direct methods       
定义静态方法的标记
# virtual methods      
定义非静态方法的标记
构造函数的返回类型为V,名字为<init>
 
if-eq p1, v0, :cond_8 
表示如果p1v0相等,则执行cond_8的流程:
    :cond_8
    invoke-direct {p0}, Lcom/paul/test/a;->d()V
调用com.paul.test.ad()方法
if-ne p1, v0, :cond_b 
表示不相等则执行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
 
大概意思就是调用com.paul.test.asetPressed方法,然后再调用父类ViewonKeyUp方法,最后 return v0
 
第一期,大家就好好理解一下smali,第二期会讲一些关于我修改smali的过程和理解,顺便也是我回顾和整理的一个过程,同为学习者,大家一起努力吧。
  评论这张
 
阅读(273)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017