SMALI

Smali is the assembly language used to represent Android's DEX bytecode. This guide organizes the most important instructions and concepts into a comprehensive and easy-to-understand format, providing clarity on the various components of Smali code.
Smali File Structure

Data types
Syntax
Meaning
V
Void
Z
Boolean
B
Byte
S
Short
C
Char
F
Float
I
Int
J
Long (64-bit)
D
Double (64-bit)
\[
Array (e.g., [B → byte[])
L
Fully qualified class name (e.g. Ljava/lang/Object)
Annotations
Purpose
Java code
Smali equivalent
Inner / member classes
(implicit, compiler adds when you declare inner classes)
smali .annotation system Ldalvik/annotation/MemberClasses; value = { Lcom/example/Outer$Inner;, Lcom/example/Outer$Nested; } .end annotation
Enclosing class
(added automatically for inner classes)
smali .annotation system Ldalvik/annotation/EnclosingClass; value = Lcom/example/Outer; .end annotation
Enclosing method
(added for anonymous/local classes inside a method)
smali .annotation system Ldalvik/annotation/EnclosingMethod; value = Lcom/example/Outer;->myMethod()V .end annotation
Generics (Signature)
java class MyClass<T> { }
smali .annotation system Ldalvik/annotation/Signature; value = { "<T:", "Ljava/lang/Object;", ">","Ljava/lang/Object;" } .end annotation
Throws (declared exceptions)
java void read() throws IOException, InterruptedException;
smali .annotation system Ldalvik/annotation/Throws; value = { Ljava/io/IOException;, Ljava/lang/InterruptedException; } .end annotation
Annotation default (in annotation interface)
java @interface MyAnnotation { String value() default "defaultText"; }
smali .annotation system Ldalvik/annotation/AnnotationDefault; value = .subannotation Lcom/example/MyAnnotation; value = "defaultText" .end subannotation .end annotation
Deprecated (runtime)
java @Deprecated class OldClass { }
smali .annotation runtime Ljava/lang/Deprecated; .end annotation
Nullable (runtime)
java @Nullable String name;
smali .annotation runtime Landroidx/annotation/Nullable; .end annotation
SerializedName (runtime)
java @SerializedName("user_name") String userName;
smali .annotation runtime Lcom/google/gson/annotations/SerializedName; value = "user_name" .end annotation
SuppressLint (build)
java @SuppressLint({"NewApi","Recycle"}) void foo() { }
smali .annotation build Landroid/annotation/SuppressLint; value = { "NewApi", "Recycle" } .end annotation
Custom annotation
java @MyCustomAnnotation("Hello") class MyClass {}
smali .annotation runtime Lcom/example/MyCustomAnnotation; value = "Hello" .end annotation
Registers
In Dalvik, the registers are 32 bits long for any type of data. For 64-bit data types, (e.g. long,double), two registers are used.
Local registers (
vx): local variables and temporary values (some registers are used for internal operations by the decompiler)Parameter registers (
px): Used for passing parameters in functions (P0typically representing thethisoperator)
.locals
number of local registers
.registers
total number of registers (if virtual method, there is also a register for the implicit parameter this)
Static
public static int addInteger2(int num1, int num2) {
int res = num1 + num2;
return res;
}
.method public static addInteger(II)I
.locals 1
.param p0, "num1" # I
.param p1, "num2" # I
.line 13
add-int v0, p0, p1
.line 14
.local v0, "res":I
return v0
.end method.method public static addInteger(II)I
.registers 3
.param p0, "num1" # I
.param p1, "num2" # I
.line 13
add-int v0, p0, p1
.line 14
.local v0, "res":I
return v0
.end methodVirtual
public int addInteger(int num1, int num2) {
int res = num1 + num2;
return res;
}.method public addInteger(II)I
.locals 1
.param p1, "num1" # I
.param p2, "num2" # I
.line 7
add-int v0, p1, p2
.line 8
.local v0, "res":I
return v0
.end method.method public addInteger(II)I
.registers 4
.param p1, "num1" # I
.param p2, "num2" # I
.line 7
add-int v0, p1, p2
.line 8
.local v0, "res":I
return v0
.end methodInitialization and return
Command
Description
Example (Java/Smali)
move vx,vy
Moves the content of vy into vx.
int a = 12;
mov v0, 0xc
const/4 vx,lit4
Puts the 4-bit constant into vx
Alternatives:
const vx, value: values higher than 7const/16: 16-bit constantconst/high16:high 16-bit constant
int level = 3;
const/4 v0, 0x5
new-array vx,vy,type_id
Generates a new array of type_id type and vy element size, then stores the reference in vx.
byte[] bArr = {0, 1, 2, 3, 4};
const/4 v0, 0x5
new-array v0, v0, [B
const vx, lit32
Puts a 32-bit integer constant into vx.
int level = 10000;
const vx, 0x2710
const-string vx,string_id
Puts a reference to a string constant identified by string_id into vx.
String name = "Player";
const-string v5, "Player"
iget vx, vy, field_id
Reads an instance field into vx, where the instance is referenced by vy.
return this.highScore;
iget v0, p0, Lde/fgerbig/spacepeng/services/Profile;->highScore:I
return v0
iput vx,vy, field_id
Puts vx into an instance field, where the instance is referenced by vy.
this.lastPlayedLevel = lastPlayedLevel2;
iput p1, p0, Lde/fgerbig/spacepeng/services/Profile;->lastPlayedLevel:I
Arrays
In Smali, arrays are handled with the new-array instruction, which creates an array and stores it in a register. Elements are accessed via the aget and aput instructions.
Example:
int[] numbers = new int[]{10, 20};.locals 3 ; We assume the method has at least 3 local registers: v0, v1, v2
.line 10
# 1. Load the array size (2) into register v1
const/4 v1, 0x2
# 2. Create a new 'int' array ([I) of size 2 and save it to v0
new-array v0, v1, [I
.line 11
# 3. Insert value 10 at index 0
const/16 v2, 0xa # Load 10 (0xa in hexadecimal) into register v2
const/4 v1, 0x0 # Load index 0 into register v1
aput v2, v0, v1 # Assign content of v2 (10) to array v0 at index v1 (0)
.line 12
# 4. Insert value 20 at index 1
const/16 v2, 0x14 # Load 20 (0x14 in hexadecimal) into register v2
const/4 v1, 0x1 # Load index 1 into register v1
aput v2, v0, v1 # Assign content of v2 (20) to array v0 at index v1 (1)Arithmetic and binary operators
Operation
Description
Java example
Smali example
add-int vx,vy,vz
vy + vz → vx
value = value + 1;
add-int/lit8 v5, v5, 0x1
sub-int vx,vy,vz
vy - vz → vx
value = value - 1;
sub-int/lit8 v5, v5, 0x1
mul-int vx,vy,vz
vy * vz → vx
value = value * 50;
mul-int/lit8 v6, v1, 0x32
div-int vx,vy,vz
vy / vz → vx
value = value / 2;
div-int v4, v1, 0x2
rem-int vx,vy,vz
vy % vz → vx
Math.abs(step2 % 4);
rem-int/lit8 v0, p1, 0x4
and-int vx,vy,vz
vy & vz → vx
int value = b & 127;
and-int/lit8 v1, p3, 0x1f
or-int vx,vy,vz
vy | vz → vx
int result = a | b;
xor-int v1, v2, v3
xor-int vx,vy,vz
vy ^ vz → vx
int result = a ^ b;
xor-int v1, v2, v3
Flow operations
Comparison
Syntax
Description
if-eqz vx, target
Jumps to target if vx == 0
if-nez vx, target
Jumps to target if vx != 0
if-ltz vx, target
Jumps to target if vx < 0
if-gez vx, target
Jumps to target if vx >= 0
if-gtz vx, target
Jumps to target if vx > 0
if-lez vx, target
Jumps to target if vx <= 0
if-eq vx, vy, target
Jumps to target if vx == vy
if-ne vx, vy, target
Jumps to target if vx != vy
if-lt vx, vy, target
Jumps to target if vx < vy
if-ge vx, vy, target
Jumps to target if vx >= vy
if-gt vx, vy, target
Jumps to target if vx > vy
if-le vx, vy, target
Jumps to target if vx <= vy
GOTO
Command
Description
Smali example
goto :label
Unconditionally jumps to the specified label in the code.
goto :label_1
goto/16 :label
Unconditionally jumps to a label, used when the target is far in code.
goto/16 :label_2
goto/32 :label
Unconditionally jumps to a label for even farther targets.
goto/32 :label_3
Methods
Command
Description
Java example
Java example
invoke-virtual {parameters}, methodtocall
Invokes a virtual method with parameters
this.ds.increaseScore(value)
invoke-virtual {v5, v6}, Lde/fgerbig/spacepeng/systems/DirectorSystem;->increaseScore(I)V
invoke-direct {parameters}, methodtocall
Invokes a method with parameters without virtual method resolution (private methods)
DoubleShot doubleShot = new DoubleShot();
invoke-direct {v0}, Lde/fgerbig/spacepeng/components/powerup/DoubleShot;-><init>()V
invoke-static {parameters}, methodtocall
Invokes a static method with parameters
MathUtils.random((float) MIN_DELAY, (float) MAX_DELAY);
invoke-static {v0, v1}, Lcom/example/MathUtils;->random(FF)F
invoke-interface {parameters}, methodtocall
Invokes an interface method
itrt.hasNext();
invoke-interface {v3}, Ljava/util/Iterator;->hasNext()Z
Sget-object
Retrieves the value of a static object field and puts it into a register
String name = MyClass.staticField;
sget-object v0, Lcom/example/MyClass;->staticField:Ljava/lang/String;
Method Definitions
A method in Smali starts with a .method directive and is followed by the method signature, return type, and parameters.
Example:
.method public myMethod(I)V # A method named 'myMethod' that takes an integer and returns void
.locals 1 # Defines 1 local register
return-void # Return from the method
.end methodOther Instructions
move: Moves the value from one register to another.return-void: Returns from a method with no value.return: Returns a value from a method.
SMALI snippets
Printing Variables
String example = "Example!!!";
System.out.println(example);.line 14
const-string v0, "Example!!!"
.line 15
.local v0, "example":Ljava/lang/String;
sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(Ljava/lang/String;)VBase64 encoding of byte array
System.out.println(Base64.encodeToString(, Base64.DEFAULT));# Base64 encoding of byte array
const/4 v5, 0x0 # Reference to your byte array
invoke-static {v2, v5}, Landroid/util/Base64;->encodeToString([BI)Ljava/lang/String;
move-result-object v5
# Print the encoded string
sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
invoke-virtual {v1, v5}, Ljava/io/PrintStream;->println(Ljava/lang/String;)Vcode>Toast creation
Toast.makeText(this, "My message!!!", Toast.LENGTH_LONG).show();const/4 v0, 0x1
const-string v1, "My message!!!"
invoke-static {p0, v1, v0}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
move-result-object v0
invoke-virtual {v0}, Landroid/widget/Toast;->show()VLast updated