Android smali语法

本文详细介绍了Android smali语法,包括数据类型、运算、类名、数组、类的定义、寄存器使用、注解以及创建数组等内容。smali是Dalvik虚拟机使用的汇编语言,与Java代码有相似之处,如数据类型的表示、类名的定义以及数组的声明。此外,文章还讲解了如何给寄存器赋值、进行值的判断以及使用移位指令等。

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
Vvoid (用于返回类型)-
Zboolean不同
Bbyte-
Sshort-
Cchar-
Iint-
Jlong (64 bits)不同
Ffloat-
Ddouble (64 bits)-

运算

smali

mul-int v0, p1, p2

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

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

类名

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

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

数组

smali数组Java数组
[Iint[]
[[Iint[][]
[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赋值给vxconst-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_0if (v0 == v1) cond_0
if-ne v0, v1, :cond_0if (v0 != v1) cond_0
if-gt v0, v1, :cond_0if (v0 > v1) cond_0
if-ge v0, v1, :cond_0if (v0 >= v1) cond_0
if-lt v0, v1, :cond_0if (v0 < v1) cond_0
if-le v0, v1, :cond_0if (v0 <= v1) cond_0
if-eqz v0, :cond_0if (v0 == 0) cond_0
if-nez v0, :cond_0if (v0 != 0) cond_0
if-gtz v0, :cond_0if (v0 > 0) cond_0
if-gez v0, :cond_0if (v0 >= 0) cond_0
if-ltz v0, :cond_0if (v0 < 0) cond_0
if-lez v0, :cond_0if (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;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值