Android smali语法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Rozol/article/details/88368358

smali语法


本文由 Luzhuo 编写,转发请保留该信息.
原文: https://blog.csdn.net/Rozol/article/details/88368358


smali是什么, 官方的简介

smali/baksmali is an assembler/disassembler for the dex format used by dalvik, Android’s Java VM implementation. The syntax is loosely based on Jasmin’s/dedexer’s syntax, and supports the full functionality of the dex format (annotations, debug info, line info, etc.)
smali / baksmali是Android的Java VM实现dalvik使用的dex格式的汇编程序/反汇编程序。语法松散地基于Jasmin的/ dedexer的语法,并支持dex格式的全部功能(注释,调试信息,行信息等)

Java代码

public int show(String str){
    return 1;
}

smali代码

# virtual methods
.method public show(Ljava/lang/String;)I
    .locals 1
    .param p1, "str"    # Ljava/lang/String;

    .line 22
    const/4 v0, 0x1

    return v0
.end method

数据类型 / 对象 / 数组 的写法, 对于经常JNI开发的童鞋肯定非常熟悉, 没错, 跟javap生成签名类型是一样的.

数据类型

smali类型 java类型 Description
V void (用于返回类型) -
Z boolean 不同
B byte -
S short -
C char -
I int -
J long (64 bits) 不同
F float -
D double (64 bits) -

运算

smali

mul-int v0, p1, p2

add-int / add-long / add-float / add-double / add-int/lit16 / add-int/lit8

smali运算符 Description int long float double
add-int v0, p1, p2 v0 = p1 + p2
sub-int v0, p1, p2 v0 = p1 - p2
mul-int v0, p1, p2 v0 = p1 * p2
div-int v0, p1, p2 v0 = p1 / p2
rem-int v0, p1, p2 v0 = p1 % p2
and-int v0, p1, p2 v0 = p1 & p2 × ×
or-int v0, p1, p2 v0 = p1 │ p2 × ×
xor-int v0, p1, p2 v0 = p1 ^ p2 × ×
shl-int v0, p1, p2 v0 = p1 << p2 × ×
shr-int v0, p1, p2 v0 = p1 >> p2 × ×
ushr-int v0, p1, p2 v0 = p1 >>> p2 × ×
add-int/2addr v0, v1 v0 = v0 + v1
sub-int/2addr v0, v1 v0 = v0 - v1
mul-int/2addr v0, v1 v0 = v0 * v1
div-int/2addr v0, v1 v0 = v0 / v1
rem-int/2addr v0, v1 v0 = v0 % v1
and-int/2addr v0, v1 v0 = v0 & v1 × ×
or-int/2addr v0, v1 v0 = v0 │ v1 × ×
xor-int/2addr v0, v1 v0 = v0 ^ v1 × ×
shl-int/2addr v0, v1 v0 = v0 << v1 × ×
shr-int/2addr v0, v1 v0 = v0 >> v1 × ×
ushr-int/2addr v0, v1 v0 = v0 >>> v1 × ×
add-int/lit16 v0, v1, lit16 v0 = v1 + lit16 × × ×
sub-int/lit16 v0, v1, lit16 v0 = v1 - lit16 × × ×
mul-int/lit16 v0, v1, lit16 v0 = v1 * lit16 × × ×
div-int/lit16 v0, v1, lit16 v0 = v1 / lit16 × × ×
rem-int/lit16 v0, v1, lit16 v0 = v1 % lit16 × × ×
and-int/lit16 v0, v1, lit16 v0 = v1 & lit16 × × ×
or-int/lit16 v0, v1, lit16 v0 = v1 │ lit16 × × ×
xor-int/lit16 v0, v1, lit16 v0 = v1 ^ lit16 × × ×
add-int/lit8 v0, v1, lit8 v0 = v1 + lit8 × × ×
sub-int/lit8 v0, v1, lit8 v0 = v1 - lit8 × × ×
mul-int/lit8 v0, v1, lit8 v0 = v1 * lit8 × × ×
div-int/lit8 v0, v1, lit8 v0 = v1 / lit8 × × ×
rem-int/lit8 v0, v1, lit8 v0 = v1 % lit8 × × ×
and-int/lit8 v0, v1, lit8 v0 = v1 & lit8 × × ×
or-int/lit8 v0, v1, lit8 v0 = v1 │ lit8 × × ×
xor-int/lit8 v0, v1, lit8 v0 = v1 ^ lit8 × × ×
shl-int/lit8 v0, v1, lit8 v0 = v1 << lit8 × × ×
shr-int/lit8 v0, v1, lit8 v0 = v1 >> lit8 × × ×
ushr-int/lit8 v0, v1, lit8 v0 = v1 >>> lit8 × × ×

类名

smali类名 java类名
Ljava/lang/String; java.lang.String
Ljava/lang/Object; java.lang.Object
L全/类/名; 全.类.名

smali类名写法要注意, 最前面L开头, 最后;结尾

数组

smali数组 Java数组
[I int[]
[[I int[][]
[Ljava/lang/String; String[]

smali数组在类型左侧加[号, 几维就加几个, 最多255维.

类的定义

Java代码

public class BaseData {
    public int add(int x, int y){
        return x * y;
    }
}

Smali代码

.class public Lme/luzhuo/smalidemo/BaseData; // 本类
.super Ljava/lang/Object; // 父类
.source "BaseData.java" // 文件名


# direct methods
// 构造方法, 方法名为<init>
.method public constructor <init>()V
    .locals 0

    .line 20
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V

    return-void
.end method


# virtual methods
// 普通方法 / add:方法名 / II:返回类型 / I:返回类型
.method public add(II)I
    .locals 1
    .param p1, "x"    # I  // 参数
    .param p2, "y"    # I

    .line 26 // 该函数在原.source中的位置(含注释)
    mul-int v0, p1, p2

    return v0
.end method

类的定义: 本类 / 父类 / 文件名

.class public Lme/luzhuo/smalidemo/BaseData; // 本类
.super Ljava/lang/Object; // 父类
.source "BaseData.java" // 文件名

属性的定义: 属性名 / 属性类型

# static fields
// 属性: .field 修饰符 属性名:属性类型
.field private static final TAG:Ljava/lang/String; = "PropActivity"

方法的定义: 方法名 / 参数类型 / 参数名 / 返回类型 / 返回值

// 方法: .method 修饰符 方法名(参数类型)返回类型
.method public add(II)I
    .locals 1
    .param p1, "x"    # I  // 参数名
    .param p2, "y"    # I

    return v0  // 返回值
.end method
返回指令 Description
return-void 直接返回
return v0 返回v0
return-object v0 返回v0(对象)
return-wide v0 给v0(双寄存器的值)

特殊的方法:

// 构造方法
.method public constructor <init>()V
.end method

// 静态方法
.method public static final constructor <clinit>()V
.end method

调用方法:

const/4 v0, 0x3
const/4 v1, 0x5

// 调用方法: 类->方法
invoke-virtual {p0, v0, v1}, Lme/luzhuo/smalidemo/BaseData;->add(II)I
调用指令 Description 案例
invoke-virtual 调用一般方法 invoke-virtual {p0, v0, v1}, Lme/luzhuo/smalidemo/BaseData;->add(II)I
invoke-super 调用父类方法 invoke-super {p0, p1}, Landroid/support/v7/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V // super.onCreate(savedInstanceState);
invoke-direct 调用private/构造方法 invoke-direct {p0}, Ljava/lang/Object;-><init>()V
invoke-static 调用静态方法 invoke-static {}, Lme/luzhuo/smalidemo/BaseData;->aaa()V
invoke-interface 调用interface方法 invoke-interface {v0}, Lme/luzhuo/smalidemo/Inter;->mul()V

寄存器

方法内部先声明寄存器数量, 然后再写代码

.method public add(II)I
    .locals 1
    .param p1, "x"    # I
    .param p2, "y"    # I

	// 先完成上面部分的声明, 然后在这些代码
    .line 26
    mul-int v0, p1, p2

    return v0
.end method

寄存器的声明方式

.locals 0  // 声明不算参数, 需要加几个寄存器
.registers 0  // 声明算上参数, 一共需要几个寄存器

寄存器命名规则

v0 v1 v2 v... // .locals 寄存器的命名
p0 p1 p2 p... // .registers 寄存器的命名

.registers不用声明, .locals要声明
有参数, 用p表示第几个参数所占的寄存器, 从1开始

给寄存器赋值:

const/4 v0, 0x3
const-string v0, "\u4f60\u88ab\u6211\u53cd\u7f16\u8bd1\u5566\u002c\u0020\u54c8\u54c8\u54c8\u54c8"
常量指令 Description 案例
const(/4, /16, ,/high16) vx, num 把nun赋给vx寄存器, num为(4bit, 16bit, 32bit(int), 16bit(float)) const v0, 0x3
const-wide(/16, ,/high16) vx, num 把num赋给vx和vx+, num为(?, 64bit(long), 64bit(double)) const-wide v0, 0x123456L
const-string( , -jumbo) vx, string "Unicode"字符串赋给vx (一般, 过长) const-string v0, "\u4f60\u88ab..."
const-class vx, class 将Class赋值给vx const-class v0, LJava/lang/String;
  • boolean
    • const/4赋值, 1true, 0false
  • float/double
    • 0x16进制表示小数
    • long和double的16进制数后加L
// smali 给寄存器赋值, 并起名(带名称的常量)
const/16 v0, 0xa
.local v0, "a":I

// java
int a = 0xa;

// ---

// smali 给寄存器赋值对象
const/4 v2, 0x0
new-array v2, v2, [Ljava/lang/String;

// java
new String[]

值的判断指令

// smali
const/16 v0, 0xa
const/16 v1, 0x14

if-le v0, v1, :cond_0

const/16 v0, 0x1e

goto :goto_0

:cond_0
const/16 v1, 0x1e

:goto_0


// java
if (v0 <= v1) {
	cond_0
}else{
	const/16 v0, 0x1e
 	goto_0
}
// 翻译成人话: 等式不成立则往下执行
// java中写 a > b, 到这里就相反, 变成 a <= b 了.
指令 Description
if-eq v0, v1, :cond_0 if (v0 == v1) cond_0
if-ne v0, v1, :cond_0 if (v0 != v1) cond_0
if-gt v0, v1, :cond_0 if (v0 > v1) cond_0
if-ge v0, v1, :cond_0 if (v0 >= v1) cond_0
if-lt v0, v1, :cond_0 if (v0 < v1) cond_0
if-le v0, v1, :cond_0 if (v0 <= v1) cond_0
if-eqz v0, :cond_0 if (v0 == 0) cond_0
if-nez v0, :cond_0 if (v0 != 0) cond_0
if-gtz v0, :cond_0 if (v0 > 0) cond_0
if-gez v0, :cond_0 if (v0 >= 0) cond_0
if-ltz v0, :cond_0 if (v0 < 0) cond_0
if-lez v0, :cond_0 if (v0 <= 0) cond_0

移位指令

smali

.method public show()I
    const/16 v0, 0xa
    const/16 v1, 0x14
    const/4 v2, 0x0
    new-array v2, v2, [Ljava/lang/String;

    invoke-virtual {p0, v0, v1, v2}, Lme/luzhuo/smalidemo/BaseData;->add(II[Ljava/lang/String;)I

    move-result v2

    return v2
.end method
移位指令 Description
move( , /from16, /16) v0, v1 将v1值移入到v0(4bit(int), 16bit->8bit, 16bit)
move-wide( , /from16, /16) v0, v1 将v1值移入到v0(4bit, 16bit->8bit, 16bit)
move-object( , /from16, /16) v0, v1 将v1对象指针移入到v0(4bit, 16bit->8bit, 16bit)
move-result( , -object, -wide) v0 将上条指令计算结果, 移入到v0(值, 对象指针, 双寄存器值)
move-exception v0 将异常移入到v0

实例字段指令

smali

.method public static final aaa()V
    .locals 2

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

    const-string v1, "sfsdf"
    invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V

    return-void
.end method

iget / aget / sget: 数字 / 数组 / 静态

实例字段指令 Description
iget 取值(int)
iget-wide 取值(双寄存器值)
iget-object 取值(对象指针)
iget-boolean 取值(bool)
iget-byte 取值(字节)
iget-char 取值(字符)
iget-short 取值(short)
iput 赋值(int)
iput-wide 赋值(双寄存器值)
iput-object 赋值(对象指针)
iput-boolean 赋值(bool)
iput-byte 赋值(字节)
iput-char 赋值(字符)
iput-short 赋值(short)

其他

注解

smali

.method protected onCreate(Landroid/os/Bundle;)V
    .locals 0
    .param p1    # Landroid/os/Bundle;
        .annotation build Landroid/support/annotation/Nullable;
        .end annotation
    .end param

	//...

    return-void
.end method

java

protected void onCreate(Bundle @Nullable savedInstanceState) {
}

创建数组

smali

const/4 v2, 0x0
new-array v2, v2, [Ljava/lang/String;
展开阅读全文

没有更多推荐了,返回首页