smali语法小结

smali语言是Davlik的寄存器语言,语法上和汇编语言相似,Dalvik VM与JVM的最大的区别之一就是Dalvik VM是基于寄存器的。基于寄存器的意思是,在smali里的所有操作都必须经过寄存器来进行。Link

Smali-数据类型

Davlik字节码中,寄存器都是32位的,能够支持任何类型,64位类型(Long/Double)用2个寄存器表示。Dalvik字节码有两种类型:原始类型;引用类型(包括对象和数组)@link

M1.基本数据类型

V void
Z boolean
B byte
S short
C char
I int
J long(64位)
F float
D double(64位)
J、Z两个不是对应类型的首字母
基本数据类型示例:
.method public final pubFinalMethod()V //返回值
.field private boType:Z    // boolean
.field private byteType:B  // byte
.field private shortType:S // short
.field private charType:C  // char
.field private intType:I   // int
.field private longType:J  //long
.field private floatType:F // float
.field private doubleType:D // double

M2.对象类型

Lpackage/name/ObjectName; 相当于java中的package.name.ObjectName; L 表示这是一个对象类型

,package/name 该对象所在的包 ,ObjectName 对象名称 , 标识对象名称的结束。

.method private priParamsOne(Ljava/lang/String;)V // 对象参数类型
new-instance v1, Ljava/lang/StringBuilder;        // 对象实例化
invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V // 对象调用
invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; // 返回值类型

M3.数组类型

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

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

对象数组的表示形式:

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

.method private varargs priParamsUncertain(Ljava/lang/String;[Ljava/lang/String;)V

Smali-方法

smali方法结构 link
#direct methods
.method <访问权限> [修饰关键字] <方法原型>
    <.registers>
    [.param]
    [.prologue]
    [.line]
    <.local>
    <代码体>
.end method
#direct methods是注释,是baksmali添加的,访问权限和修饰关键字跟字段是一样的。
方法原型描述了方法的名称、参数与返回值。
.registers 指令指定了方法中寄存器的总数,这个数量是参数和本地变量总和。
.param表明了方法的参数,每个.param指令表示一个参数,方法使用了几个参数就有几个.parameter指令。
.prologue指定了代码的开始处,混淆过的代码可能去掉了该指令。
.line指明了该处代码在源代码中的行号,同样,混淆后的代码可能去掉了行号。
.local 使用这个指定表明方法中非参寄存器
s1.方法声明
private void priParamsUncertain(String str0, String... params) // java
.method private varargs priParamsUncertain(Ljava/lang/String;[Ljava/lang/String;)V // smali
格式:.method + 访问修饰符 + 方法名(参数表) + 返回值类型
s2.调用结构
(StringBuilder)v1.append(v2); // JAVA
invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
invoke-virtual调用方法声明
{v1, v2}数据寄存器
对象 -> 方法名(参数类型)返回值
invoke-virtual 非静态方法调用
invoke-static  静态方法调用
invoke-direct  构造方法调用?
invoke-super   调用父类方法
invoke-interface 调用接口
s3.寄存器
本地寄存器(local register,非参寄存器)用v开头数字结尾的符号来表示,如v0、v1、v2、…,
参数寄存器(parameter register)用p开头数字结尾的符号来表示,如p0、p1、p2、…,
.registers 用来标明方法中寄存器的总数,即参数寄存器和非参寄存器的总数。
.local 0,标明在这个函数中最少要用到的本地寄存器的个数,出现在方法中的第一行。
如 .local 4,则可以使用的寄存器是v0-v3。
当一个方法被调用的时候,方法的参数被置于最后N个寄存器中。
在实例函数中,p0代指“this”,p1表示函数的第一个参数,p2代表函数中的第二个参数…,
在static函数中,p1表示函数的第一个参数,p2代表函数中的第二个参数…,因为Java的static方法中没有this方法。
s4.其他
.method // 方法的开始
.end method // 方法结束
move-result(返回基本数据类型)和move-result-object(返回对象)
获取和操作静态成员变量和实例成员变量有不同的指令。
读取的指令有:iget、sget、iget-boolean、sget-boolean、iget-object、sget-object等,
赋值的指令有:iput、sput、iput-boolean、sput-boolean、iput-object、sput-object等。
带“-object”表示操作的成员变量是对象类型,没有“-object”后缀的表示操作的成员变量对象是基本数据类型,特别地boolean类型则使用带“-boolean”的指令操作。
Smali与java声明方法参考
.method private priParamsVoid()V // smali
private void priParamsVoid()     // java
.method private varargs priParamsUncertain(Ljava/lang/String;[Ljava/lang/String;)V
private void priParamsUncertain(String str0, String... params)
.method private priParamsType(ILjava/lang/Long;Ljava/lang/String;Ljava/lang/Object;)V
private void priParamsType(int var, Long varL, String str, Object object)
.method private priParamsInf(Lcom/simple/dec/basic/basic/basic1/ClazzInterface;)V
private void priParamsInf(ClazzInterface clazzInterface)
smali与java方法声明结构非常相似

Smali-对象

头文件
.class <访问权限> [关键修饰字] <类名>;
.super <父类名>;
.source <源文件名>
.implements <实现接口>
构造方法
# direct methods
.method static constructor <clinit>()V // 初始化静态变量构造方法
    .locals 1
    .prologue
    .line 10
    const/4 v0, 0x0
    sput-boolean v0, Lcom/simple/dec/basic/basic/basic2/StateTry;->isLoop:Z
    return-void
.end method
.method public constructor <init>()V // 默认构造方法
    .locals 0
    .prologue
    .line 8
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
    return-void
.end method
super-implements
.super Lcom/disney/common/BaseActivity;
.implements Lcom/burstly/lib/ui/IBurstlyAdListener;
内部类
# annotations
.annotation system Ldalvik/annotation/MemberClasses;
    value = {
        Lcom/simple/dec/basic/basic/basic1/ClazzJava$InnerInterface;,
        Lcom/simple/dec/basic/basic/basic1/ClazzJava$InnerAbsClazz;,
        Lcom/simple/dec/basic/basic/basic1/ClazzJava$InnerPubStaticClazz;,
        Lcom/simple/dec/basic/basic/basic1/ClazzJava$InnerPubClazz;,
        Lcom/simple/dec/basic/basic/basic1/ClazzJava$InnerDefClazz;,
        Lcom/simple/dec/basic/basic/basic1/ClazzJava$InnerPriClazz;
    }
.end annotation

Smali-语句

M1.if判断语句

if判断一共有12条指令:

if-eq vA, VB, cond_** 如果vA等于vB则跳转到cond_**。相当于if (vA==vB)
if-ne vA, VB, cond_** 如果vA不等于vB则跳转到cond_**。相当于if (vA!=vB)
if-lt vA, VB, cond_** 如果vA小于vB则跳转到cond_**。相当于if (vA<vB)
if-le vA, VB, cond_** 如果vA小于等于vB则跳转到cond_**。相当于if (vA<=vB)
if-gt vA, VB, cond_** 如果vA大于vB则跳转到cond_**。相当于if (vA>vB)
if-ge vA, VB, cond_** 如果vA大于等于vB则跳转到cond_**。相当于if (vA>=vB)

if-eqz vA, :cond_** 如果vA等于0则跳转到:cond_** 相当于if (VA==0)
if-nez vA, :cond_** 如果vA不等于0则跳转到:cond_**相当于if (VA!=0)
if-ltz vA, :cond_** 如果vA小于0则跳转到:cond_**相当于if (VA<0)
if-lez vA, :cond_** 如果vA小于等于0则跳转到:cond_**相当于if (VA<=0)
if-gtz vA, :cond_** 如果vA大于0则跳转到:cond_**相当于if (VA>0)
if-gez vA, :cond_** 如果vA大于等于0则跳转到:cond_**相当于if (VA>=0)

M2.switch分支语句

Switch语句的smali文件解释结构

整形顺序结构switch(int)
    :pswitch_data_0
    .packed-switch 0x0
        :pswitch_0
        :pswitch_1
.end packed-switch
整形非顺序结构switch(int)
    :sswitch_data_0
    .sparse-switch
        0x0 -> :sswitch_0
        0x1 -> :sswitch_1
        0xa -> :sswitch_2
.end sparse-switch
switch(String)
    :pswitch_data_0
    .packed-switch 0x41
        :pswitch_0
        :pswitch_1
    .end packed-switch

    :pswitch_data_1
    .packed-switch 0x0
        :pswitch_2
        :pswitch_3
    .end packed-switch

M3.循环语句

常用的循环结构有:迭代器循环,for/foreach循环,while/do-while循环。

# virtual methods
.method public statementFor()Z
    .locals 4
    .prologue
    .line 17
    const/4 v0, 0x0
    .local v0, "a":I
    :goto_0
    const/16 v1, 0x64
    if-ge v0, v1, :cond_0 // 结束循环条件
    .line 18
    const-string v1, "StateLoop"
    new-instance v2, Ljava/lang/StringBuilder;
    invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()V
    const-string v3, ""
    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    move-result-object v2
    invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;
    move-result-object v2
    invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
    move-result-object v
    invoke-static {v1, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
    .line 17
    add-int/lit8 v0, v0, 0x1
    goto :goto_0 // 通过goto实现循环
    .line 20
    :cond_0
    const/4 v1, 0x0
    return v1
.end method
for/foreach循环,while/do-while 几种循环结构smali语法均通过goto实现,内部嵌入if-xxx 实现跳出循环。

M4.try/catch语句

# virtual methods
.method public statementTry()Z
    .locals 4
    .prologue
    .line 14
    const-wide/16 v2, 0x3e8
    :try_start_0
    invoke-static {v2, v3}, Ljava/lang/Thread;->sleep(J)V
    :try_end_0
    .catch Ljava/lang/InterruptedException; {:try_start_0 .. :try_end_0} :catch_0
    .line 18
    :goto_0
    const/4 v1, 0x1
    return v1
    .line 15
    :catch_0
    move-exception v0
    .line 16
    .local v0, "e":Ljava/lang/InterruptedException;
    invoke-virtual {v0}, Ljava/lang/InterruptedException;->printStackTrace()V
    goto :goto_0
.end method

工具:

JesusFreke/smali dex/smali

Dalvik opcodes

参考:

Smali语法详解

smali 语言语法 小菜的爱

[求助]关于SMALI语法最早介绍

静态分析Android程序——smali文件解析 CSDN

Smali和逆向分析推酷


V void

Z boolean

B byte

S short

C char

I int

J long(64位)

F float

D double(64位)

时间: 2024-10-10 10:03:08

smali语法小结的相关文章

Smali语法简单介绍

Smali语言其实就是Davlik的寄存器语言: Smali语言就是android的应用程序.apk通过apktool反编译出来的都有一个smali文件夹,里面都是以.smali结尾的文件,文件的展示语言. Smali语法简单介绍如下: Davlik字节码中,寄存器都是32位的,能够支持任何类型,64位类型(Long/Double)用2个寄存器表示: Dalvik字节码有两种类型:原始类型:引用类型(包括对象和数组)   原始类型:v   void  只能用于返回值类型 Z   boolean

Swift 语法小结

Swift 语法小结 1.  Optional 就是枚举 An Optional is just an enum enum Optional<T>{ case None case Some(T) } 2.Array的声明 var a=Array<String>() var a=[String]() let a=["A","B","C"]不可改 let b=a[3] 遍历Array可使用for in for array in

apk反汇编之smali语法

类型 Dalvik的字节码中拥有两个主要的类型:基类和引用类型.引用类型 引用类型是对象和数组,其他的一切都是基类   基类被一个简单的字符描述.我没有提出这些缩写词———他们实际以字符串的形式存储于dex文件中 他们被定义与dex格式网页文档中(在AOSP库中的路径是dalvik/docs/dex-format.html) V  空类型---仅仅可以用来作为返回类型 Z  Boolean 布尔型 B  Byte字节型 S  Short短整型(16位) C  Char字符型 I  Int 整形

Smali语法

看阿里巴巴的<深入探索Android热修复>,里面的代码看不懂,一查才知道是Smali语法,百度了语法,转载如下 转载自smali 语言语法 1.smali apk文件通过apktool反编译出来的都有一个smali文件夹,里面都是以.smali结尾的文件.smali语言是Davlik的寄存器语言,语法上和汇编语言相似,Dalvik VM与JVM的最大的区别之一就是Dalvik VM是基于寄存器的.基于寄存器的意思是,在smali里的所有操作都必须经过寄存器来进行. 2.基本数据类型 B-by

安卓破解软件需懂的Smali语法

Smali中语法: 类型 v   void  只能用于返回值类型 Z   boolean B   byte S   short C   char I    int J    long 2个寄存器 F   float D   double  2个寄存器 对象类型:Lpackage/name/ObjectName;  相当于java中的package.name.ObjectName;解释如下: L:表示这是一个对象类型 package/name:该对象所在的包 ::表示对象名称的结束 数组的表示形式

XML语法小结

语法结构主要要求: (1)有且仅有一个根元素. 根元素也称文档元素,整个 XML 文档的其他元素都包含在根元素中,并通过嵌套形成树 型结构.除了根元素外,其他元素都是子元素. (2)每个元素必须有开始标记和结束标记,除非用特定的空元素标记"<元素/>":  开始标记的格式是:<标记名称> 结束标记的格式是:</标记名称> 开始标记和结束标记将 XML 文档中的数据进行结构化组织,确定元素内容.范围和相互 关系. (3)元素必须正确嵌套.元素嵌套时不允

smali语法积累记录

1.constructor 我们知道运行一个类的时候会先调用static方法中的内容,比如: static { System.loadLibrary("qihooTest"); } 为什么呢? 上面这段代码用smali语言写出来是这样的: .method static constructor <clinit>()V #不带参数的构造方法 .locals 1 .prologue .line 64 const-string v0, "qihooTest" i

smali语法(二)

一.smali的包中信息 .class public Lcom/aaaaa; .super Lcom/bbbbb; .source "ccccc.java" 1.它是com.aaaaa这个package下的类 2.继承自com.bbbbb 3.由ccccc.java编译得到的smali文件 二.smali中的声明 # annotations .annotation system Ldalvik/annotation/MemberClasses; value = {Lcom/aaa$qq

mongodb 语法小结

数据库 一个mongodb中可以建立多个数据库. MongoDB的默认数据库为"db",该数据库存储在data目录中. MongoDB的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中. "show dbs" 命令可以显示所有数据的列表. 执行 "db" 命令可以显示当前数据库对象或集合. 运行"use"命令,可以连接到一个指定的数据库. > show dbs admin 0