0
点赞
收藏
分享

微信扫一扫

2.Smali的基础语法

小黑Neo 2022-03-15 阅读 37
java

一.smali的基础语法

1.smali数据类型与Java语言的对照关系

B---byte            
C---char           
D---double         
F---float                
I---int             
J---long            
S---short            
V---void
Z---boolean


[XXX---array Lxxx/yyy---object     数组
[I       int数组
[Z       布尔值数组

2.smali的方法定义规则

方法的一般定义为 Func-Name (Para-Type1Para-Type2Para-Type3...)Return-Type 
参数与参数之间没有任何的间隔

如:

Hello()V                 表示:void hello() 调用时无需参数,同时无返回值。

Hello(III)Z              
表示:Boolean hello(int,int,int)调用时需要传递三个int参数。返回值为boolean的值 

Hello(Z[I[ILjava/lang/String;J)Ljava/lang/String; 
表示: String hello(boolean,int[],int[],String,long)
调用时候需要传递(一个布尔值,一个int数组,一个string对象,一个long整形)
返回值是一个string值

3.smali语言中的一些关键字

.field private isFlag:z 定义变量

.method                 函数
.end method             函数结束

.parameter              参数
.prologue               代码开始的位置
.line 123               此方法位于第123行

invoke-super            调用父函数
invoke-direct           调用函数
invoke-static           调用静态函数

const v0, 0x1           把0x1(1)赋值给v0(0x1-----0x代表十六进制,0x1代表1)

return-void             函数返回void(无返回值)

new-instance            创建实例
iput-object             对象赋值
iget-object             调用对象

4.smali的条件跳转

e/eq    equals(等于)
ne      not equals(不等于)
z       zero (0)
g       greater(大于)
l       Less(小于)
lt      less than(小于)
gt      greater than(大于)

"if-eq vA, vB, :cond_**"     如果vA等于vB则跳转到:cond_**
"if-ne vA, vB, :cond_**"     如果vA不等于vB则跳转到:cond_**

"if-le vA, vB, :cond_**"     如果vA小于等于vB则跳转到:cond_**
"if-ge vA, vB, :cond_**"     如果vA大于等于vB则跳转到:cond_**

"if-lt vA, vB, :cond_**"     如果vA小于vB则跳转到:cond_**
"if-gt vA, vB, :cond_**"     如果vA大于vB则跳转到:cond_**

"if-eqz vA, :cond_**"        如果vA等于0则跳转到:cond_**
"if-nez vA, :cond_**"        如果vA不等于0则跳转到:cond_**

"if-lez vA, vB, :cond_**"    如果vA小于等于vB则跳转到:cond_**
"if-gez vA, vB, :cond_**"    如果vA大于等于vB则跳转到:cond_**

"if-ltz vA, :cond_**"        如果vA小于0则跳转到:cond_**
"if-gtz vA, :cond_**"        如果vA大于0则跳转到:cond_**

5.smali中类的表达

.class public Lcom/aaaaa;
.super Lcom/bbbbb;
.source "ccccc.java"

它是com.aaaaa这个package下的一个类(第1行)
继承自com.bbbbb这个类(第2行)
这是一个由ccccc.java编译得到的smali文件(第3行)

6.smali中内部类的声明

一般来说在Smali文件中是这个样子的: 
# annotations .annotation system Ldalvik/annotation/MemberClasses; 
value = { 
    Lcom/aaa$qqq; 
    Lcom/aaa$www; 
}
.end annotation 
这个声明是内部类的声明:aaa这个类它有两个成员内部类——qqq和www。

7.smali中的寄存器语法

在smali里的所有操作都必须经过寄存器来进行  

本地寄存器:用v开头数字结尾的符号来表示,如v0,v1,v2…v15..,用于方法内数 值之间的传递;
 
参数(parameter)寄存器:用p开头数字结尾的符号来表示,如p0,p1,p2…,表示该方法依次接 
收过来的参数值。
 
特别注意:p0不一定是函数中的第一个参数。在非static函数中,p0代指“this”, 
p1表示函数的第一个参数,p2代表函数中的第二个参数…而在static函数中p0才对应第一个参数。
因为Java的static方法中没有this方法

例如:
const/4 v0, 0x1 
iput-boolean v0, p0, Lcom/aaa;->IsRegistered:Z 
我们来分析一下上面的两句smali代码,首先它使用了v0本地寄存器,并把值0x1 存到v0中,
然后第二句用iput-boolean这个指令把v0中的值存放到com.aaa.IsRegistered这个成员变量中。 
即相当于:this.IsRegistered= true;
在非static函数中p0代表的是 “this”,在这里就是com.aaa实例)。

8.smali中类成员变量操作和表示

成员变量格式是:
.field public/private [static] [final] varName:<类型>。 
对于不同的成员变量也有不同的指令。 
获取的指令有:iget、sget、iget-boolean、sget-boolean、iget-object、sget- object等。 
写入的指令有:iput、sput、iput-boolean、sput-boolean、iput-object、 sput-object等。 
没有“-object”后缀的表示操作的成员变量对象是基本数据类型,带“-object” 表示操作的成员变量是对象类型,特别地,boolean类型则使用带“-boolean” 的指令操作。

sget-object v0, Lcom/aaa;->ID:Ljava/lang/String; 
解释:获取内部类aaa中的string类型的ID的值保存给V0  V0=this.ID

sget-object用来获取变量值并保存到紧接着的参数的寄存器中,
它获取 ID这个String类型的成员变量并放到v0这个寄存器中。 
注意:前面需要该变量所属的类的类型,后面需要加一个冒号和该成员变量的类型
中间是“->”表示所属关系。 

iget-object v0, p0, ->view:Lcom/aaa/view; 
解释:Lcom/aaa;(内部类不是stratic,所以p0是this)this.view=V0

可以看到iget-object指令比sget-object多了一个参数,就是该变量所在 类的实例,在这里就是p0即“this”。

9.smali语法中的代码函数的调用

invoke         调用
invoke-virtual或invoke-virtual/range :调用实例的虚方法
invoke-super或invoke-super/range :调用实例的父类/基类方法
invoke-direct或invoke-direct/range :调用实例的直接方法
invoke-static或invoke-static/range :调用实例的静态方法
invoke-interface或invoke-interface/range :调用实例的接口方法

invoke-static:用于调用static函数

const-string v0, "NDKLIB"
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
调用static void System.loadLibrary(String)来加载NDK编译的so库用的方法,这里v0就是参数"NDKLIB"。

invoke-super:调用父类方法用的指令,一般用于调用onCreate、onDestroy 等方法。

invoke-direct:调用private函数

invoke-direct {p0}, Landroid/app/TabActivity;-><init>()V
这里init()就是定义在TabActivity中的一个private函数

invoke-virtual:用于调用protected或public函数。

sget-object v0, Lcom/dddd;->bbb:Lcom/ccc;
invoke-virtual {v0, v1}, Lcom/ccc;->Messages(Ljava/lang/Object;)V
v0是bbb:Lcom/ccc
v1是传递给Messages方法的Ljava/lang/Object参数。

invoke-xxxxx/range:当方法的参数多于5个时(含5个),不能直接使用以上 的指令,而是在后面加上“/range”,range表示范围,使用方法也有所不同:

invoke-direct/range {v0 .. v5}, Lcmb/pb/ui/PBContainerActivity;->h(ILjava/lang/CharSequence;Ljava/lang/String;Landroid/content/Intent;I)Z 
需要传递v0到v5一共6个参数,这时候大括号内的参数采用省略形式,且需要连续

10.smali中对返回结果的操作

在Java代码中调用函数和返回函数结果可以用一条语句完成,而在Smali里则需要 分开来完成,在使用上述指令后,如果调用的函数返回非void,那么还需要用到 move-result(返回基本数据类型)和move-result-object(返回对象)指令:

const-string v0, "Eric"                 v0=Eric

invoke-static {v0}, Lcmb/pbi;->t(Ljava/lang/String;)Ljava/lang/String;

move-result-object v2         v2=pbi.t(Eric)

v2保存的就是调用t方法返回的String字符串。
举报

相关推荐

0 条评论