我在博客上发表一些我的Android学习心得,希望对大家能有帮助。
在前一章我们学习了如何进行Android源代码下载,这一章学习基本的Dalvik指令集编写
这一章我们就从一个基本的例子来开始Dalvik指令集的学习
1、编写smali文件
我们编写一个smali文件来学习Dalvik指令集
先学习一下HelloWorld类的框架
.class public LHelloWorld; //public class HelloWorld
.super Ljava/lang/Object; //定义父类java.lang.Object
.method public static main([Ljava/lang/String;)V
//public static void main(String[] args) 静态main()方法
.registers * //#寄存器数量待定
.parameter //高版本的baksmali需要删除,否则编译失败
.prologue //指定函数代码起始处
return-void //函数返回
.end method
这个就是一个smali文件的整体框架
为了更好的理解,我决定从一个基本的java文件反汇编为smali文件
从而更好的理解Dalvik指令与java代码对应关系
首先先在目录下面通过创建Hello.java
//测试Hello.java文件源代码
public class Hello{
int add(int a, int b) {
return a+b;
}
public static void main(String[] args) {
Hello hello = new Hello();
System.out.println(hello.add(1,1));
}
}
通过javac编译成Hello.class字节码文件(注:我的版本jdk为1.7,使用dx生成Hello.dex文件时候出现错误,强制使用1.6来进行)
在使用dx工具生成Hello.dex文件
使用baksmali.jar反汇编Hello.dex生成Hello.smali
下面我们查看baksmaliout中Hello.smali文件
//p命名法:v*表示局部变量寄存器,p*表示参数寄存器
.class public LHello;
.super Ljava/lang/Object;
.source "Hello.java"
# direct methods
.method public constructor ()V
.registers 1
.prologue
.line 1
#调用Object的构造方法,p0相当于"this" 指针
invoke-direct {p0}, Ljava/lang/Object;->()V
return-void
.end method
.method public static main([Ljava/lang/String;)V
#使用了四个寄存器
.registers 4
.prologue
#把1数据存入v2寄存器中
const/4 v2, 0x1
new-instance v0, LHello;
#调用实例的直接方法初始化
invoke-direct {v0}, LHello;->()V
#把java.io.PrintStream类的对象out获取并放入v1寄存器中
sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
#调用add(1,1)方法,
invoke-virtual {v0, v2, v2}, LHello;->add(II)I
#并把方法调用返回值放入v0寄存器中
move-result v0
#调用PrintStream中println()方法把v0的值输出
invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(I)V
return-void
.end method
# virtual methods
.method add(II)I
.registers 4
.prologue
#将p1,p2参数寄存器中的值相加,保存到v0寄存器中
add-int v0, p1, p2
#函数返回v0寄存器中的值
return v0
.end method
下面我们自己进行编写smali文件来从终端接收两个参数
并相加通过PrintStream.println()函数输出结果
下面给出我写的Hello.smali源代码
.class public LHello;
.super Ljava/lang/Object;
.source "Hello.java"
# direct methods
#初始化函数
.method public constructor ()V
.registers 1
.prologue
invoke-direct {p0}, Ljava/lang/Object;->()V
return-void
.end method
#主函数
.method public static main([Ljava/lang/String;)V
.registers 4
.prologue
const/4 v0, 0x0
const/4 v1, 0x1
#接收两个传入的参数放入v0,v1
aget-object v0, p0, v0
aget-object v1, p0, v1
#强制转化成int类型
invoke-static {v0}, Ljava/lang/Integer;->parseInt(Ljava/lang/String;)I
move-result v0
invoke-static {v1}, Ljava/lang/Integer;->parseInt(Ljava/lang/String;)I
move-result v1
#两个参数相加,值存在vo
add-int/2addr v0, v1
#将v0的值输出
sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;
invoke-virtual {v2, v0}, Ljava/io/PrintStream;->println(I)V
return-void
.end method
2、编译smali文件并测试运行
打开Android模拟器,将打包好的Hello.zip文件传输到模拟器中,可用DBMS查看
将编译出来的classes.dex文件压缩成Hello1.zip文件
最终查看结果,输出结果为5正确!
最后附上工具的百度云连接
baksmali.jar
smali.jar
链接: http://pan.baidu.com/s/1prwRW 密码: bq6w