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// 构造方法, 方法名为.method public constructor ()V    .locals 0    .line 20    invoke-direct {p0}, Ljava/lang/Object;->()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 ()V.end method// 静态方法.method public static final constructor ()V.end method

调用方法:

const/4 v0, 0x3const/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;->()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, 0x3const-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// javaint a = 0xa;// ---// smali 给寄存器赋值对象const/4 v2, 0x0new-array v2, v2, [Ljava/lang/String;// javanew String[]

值的判断指令

// smaliconst/16 v0, 0xaconst/16 v1, 0x14if-le v0, v1, :cond_0const/16 v0, 0x1egoto :goto_0:cond_0const/16 v1, 0x1e:goto_0// javaif (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, 0x0new-array v2, v2, [Ljava/lang/String;

更多相关文章

  1. LayoutInflater.inflate()方法的介绍
  2. android 笔记 --- 自定义Android主题风格theme.xml方法
  3. android工程下运行main方法的配置方法
  4. Android Studio无法新建创建android工程解决方法
  5. Android Studio设置主题 和 不支持中文的问题解决方法
  6. Flutter下载更新App的方法示例
  7. android map的使用方法

随机推荐

  1. android 让一个控件按钮居于底部的几种方
  2. android 五种数据存储之使用ContentProvi
  3. Android菜鸟日记17-SeekBar的图片效果
  4. android:hintText与android:inputType详
  5. android:paddingLeft和android:layout_ma
  6. 最近总结的android疑惑
  7. android 开发环境的搭建
  8. Android(安卓)AOSP基础(五)不会调试系统源
  9. android 相对布局属性
  10. Android的UI书写的四种方法