Smali是一种有些像汇编的用于表示Dalvik VM的bytecode的语言。(readable aem-liked format for dalvik bytecode)。 Smali最早应该来自于 smali/baksmali 汇编/反汇编工具项目,并逐渐由开源社区完善。
在整个Android的程序运行时中:
Java Bytecode → DEX Bytecode
- Java/Kotlin源代码
- Java bytecode (
.classfiles) usingjavac. - Dalvik bytecode (.dex files) using dx or D8/R8
- Natice code
ART Compiles DEX Bytecode → Native Machine Code
不同于JVM的 JIT 动态编译,ART会将dex bytecode预编译为native code机器码,这一AOT (Ahead of Time)编译过程在Android应用安装时发生。
Types 类型
- V - Void
- Z - Boolean
- B - Byte
- S - Short
- C - Char
- F - Float
- I - Int
- [ - Array
- Lpackage/name/ObjectName - Object
众所周知JVM是stack-based的虚拟机,Dalvik是register-based。stack-based和register-based最主要的区别是,他们管理 operands 操作数的方式不同。JVM使用 stack,而 Dalvik 使用虚拟的寄存器,两者都储存在 RAM 中。最终,这两种虚拟机将他们的bytecode编译为机器码,使用CPU的寄存器。
例如,以下是 5 + 3 的Java代码:
int a = 5;
int b = 3;
int c = a + b;
的JVM bycode:
iconst_5 // Push 5 onto the stack
istore_1 // Store 5 in variable 'a'
iconst_3 // Push 3 onto the stack
istore_2 // Store 3 in variable 'b'
iload_1 // Load 'a' (5) onto the stack
iload_2 // Load 'b' (3) onto the stack
iadd // Pop top two values (5, 3), add them, push result (8)
istore_3 // Store result (8) in 'c'
How the stack changes:
| Step | Stack State | Action |
|---|---|---|
| 1 | [5] | iconst_5 |
| 2 | [] | istore_1 (stores 5 in var a) |
| 3 | [3] | iconst_3 |
| 4 | [] | istore_2 (stores 3 in var b) |
| 5 | [5] | iload_1 (loads a) |
| 6 | [5, 3] | iload_2 (loads b) |
| 7 | [8] | iadd (pops 5 and 3, pushes 8) |
| 8 | [] | istore_3 (stores 8 in c) |
以下是Dalvik bytecode:
const/4 v0, 5 // Store 5 in register v0
const/4 v1, 3 // Store 3 in register v1
add-int v2, v0, v1 // v2 = v0 + v1
register-based bytecode 相比较 stack-based 能更快地被映射到 CPU registers 当中。
在 Dalvik 中,寄存器通常只有 32 bit,对于 64-bit type(如long, double)则需要两个寄存器进行储存。
- Local registers (
**Vx**)**: Used for local variables and temporary values. - Parameter registers (
**Px**): Used for passing parameters in functions, withP0typically representing thethisoperator.
.method public static add(II)I
.registers 2
add-int v0, p0, p1 # v0 = p0 + p1
return v0
.end method