In computer programming, control flow refers to the order in which statements in a program are executed. Control flow determines the sequence in which the instructions in a program are executed based on certain conditions, such as the values of variables or the results of comparisons.
What is branch statement
In computer programming, a branch statement is a statement that alters the normal control flow of a program by directing the execution to a different part of the program. Branch statements are often used in conjunction with conditional statements to create different execution paths based on conditions.
There are several types of branch statements in programming, including:
Unconditional branch statements: These statements always transfer control to the specified target location, without any condition check. Examples include the
goto
statement in C/C++ and the jmp
statement in assembly language.Conditional branch statements: These statements transfer control to the specified target location only if a certain condition is true. Examples include the
if
and else
statements in C/C++ and the branch-if
statement in assembly language.Switch statements: These statements transfer control to one of several possible target locations, based on the value of a given expression. The
switch
statement in C/C++ and the select
statement in Ada are examples of switch statements.Main control flow statements in Smali:
In
Smali
, control flow statements are used to modify the flow of execution of the program. goto
statement: This statement transfers control to a different instruction within the same method. It takes a label as an argument, which is the target instruction.Conditional branch statements: There are several conditional branch statements in
Smali
that allow you to perform different actions based on the result of a condition. These include:if-eq
/ if-ne
: These statements compare two values and branch to a specified instruction if they are equal (if-eq
) or not equal (if-ne
).if-lt
/ if-gt
: These statements compare two values and branch to a specified instruction if the first value is less than (if-lt
) or greater than (if-gt
) the second value.if-le
/ if-ge
: These statements compare two values and branch to a specified instruction if the first value is less than or equal to (if-le
) or greater than or equal to (if-ge
) the second value.Switch statement: The switch statement is used to select one of several code blocks to execute based on the value of an expression.
Smali
supports two types of switch statements:Packed switch: A packed switch is used when the switch cases are consecutive integers. In a packed switch, all the target locations for each case are stored in an array, and the index of the array is calculated based on the value of the expression being switched on. This makes accessing the target location for a given case very fast and efficient.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
int value = 3;
switch (value){
case 1:
System.out.println("1");
break;
case 2:
System.out.println("2");
break;
case 3:
System.out.println("3");
break;
default:
System.out.println("Default");
}
}
.method protected onCreate(Landroid/os/Bundle;)V
.registers 5
.param p1, "savedInstanceState" # Landroid/os/Bundle;
.prologue
.line 11
invoke-super {p0, p1}, Landroidx/appcompat/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V
.line 14
const/4 v0, 0x3
.line 15
.local v0, "value":I
packed-switch v0, :pswitch_data_28
.line 26
sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
const-string v2, "Default"
invoke-virtual {v1, v2}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
.line 28
:goto_e
return-void
.line 17
:pswitch_f
sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
const-string v2, "1"
invoke-virtual {v1, v2}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
goto :goto_e
.line 20
:pswitch_17
sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
const-string v2, "2"
invoke-virtual {v1, v2}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
goto :goto_e
.line 23
:pswitch_1f
sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
const-string v2, "3"
invoke-virtual {v1, v2}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
goto :goto_e
.line 15
nop
:pswitch_data_28
.packed-switch 0x1
:pswitch_f
:pswitch_17
:pswitch_1f
.end packed-switch
.end method
Smali
Sparse switch: A sparse switch is used when the switch cases are not consecutive integers. In a sparse switch, the target locations for each case are stored in a separate table, which is accessed using a binary search algorithm. This makes accessing the target location for a given case slower and less efficient than in a packed switch.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
int value = 10;
switch (value){
case 2:
System.out.println("2");
break;
case 10:
System.out.println("10");
break;
default:
System.out.println("Default");
}
}
Java
# virtual methods
.method protected onCreate(Landroid/os/Bundle;)V
.registers 5
.param p1, "savedInstanceState" # Landroid/os/Bundle;
.prologue
.line 11
invoke-super {p0, p1}, Landroidx/appcompat/app/AppCompatActivity;->onCreate(Landroid/os/Bundle;)V
.line 14
const/16 v0, 0xa
.line 15
.local v0, "value":I
sparse-switch v0, :sswitch_data_20
.line 23
sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
const-string v2, "Default"
invoke-virtual {v1, v2}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
.line 25
:goto_f
return-void
.line 17
:sswitch_10
sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
const-string v2, "2"
invoke-virtual {v1, v2}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
goto :goto_f
.line 20
:sswitch_18
sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
const-string v2, "10"
invoke-virtual {v1, v2}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
goto :goto_f
.line 15
:sswitch_data_20
.sparse-switch
0x2 -> :sswitch_10
0xa -> :sswitch_18
.end sparse-switch
.end method
Smali
How switch statement can be based on a String? In Java, a switch on a string can be implemented using theString.hashCode()method, which returns a hash code for the string. The hash code can be used as the switch value, with cases defined for each possible hash code. When the switch statement is executed, the hash code of the string being switched on is computed, and the corresponding case is executed.
return
statement: This statement is used to terminate the execution of a method and return a value to the calling method.These control flow statements can be combined to create more complex control flow structures in
Smali
.How return works
const/16 v1, 0xa
const/4 v2, 0x5
invoke-virtual {p0, v1, v2}, Llab/seczone64/smalifilestructure/MainActivity;->giveGraterNumber(II)I
move-result v0
Here
v0
will store the return value from giveGraterNumber
function.Statement Opcodes
One Register Compare to Zero
Syntax | Descryption | Example |
|---|---|---|
if-eqz vx, target | Equal Zero | if vx == 0 |
if-nez vx, target | Not Equal Zero | if vx ≠ 0 |
if-ltz vx, target | Less Than Zero | if vx < 0 |
if-gez vx, target | Greater Equal Zero | if vx ≥ 0 |
if-gtz vx, target | Greater Than Zero | if vx > 0 |
if-lez vx, target | Less Equal Zero | if vx ≤ 0 |
Comparing a register with Zero.
target = Location to JMP after this check.
One Register Compare To Other Register
Syntax | Descryption | Example |
|---|---|---|
if-eq vx, vy, target | Equal | if vx == vy |
if-ne vx, vy, target | Not Equal | if vx ≠ vy |
if-lt vx, vy, target | Less Than | if vx < vy |
if-ge vx, vy, target | Greater Equal | if vx ≥ vy |
if-gt vx, vy, target | Greater Than | if vx > vy |
if-le vx, vy, target | Less Equal | if vx ≤ vy |
target = Location to JMP after this check.
Example:
# virtual methods
.method public giveGraterNumber(II)I
.registers 3
.param p1, "a" # I
.param p2, "b" # I
.prologue
.line 19
if-le p1, p2, :cond_3
.line 24
.end local p1 # "a":I
:goto_2
return p1
.line 21
.restart local p1 # "a":I
:cond_3
if-ne p2, p1, :cond_7
.line 22
const/4 p1, 0x0
goto :goto_2
:cond_7
move p1, p2
.line 24
goto :goto_2
.end method
public int giveGraterNumber(int a, int b){
if (a > b){
return a;
} else if (b == a) {
return 0;
} else {
return b;
}
}
Tasks
Flip the logic of player shield in
spacepeng
app.Reverse engineer
Spacepeng
app and make player health added by each hit.Reverse engineer
Spacepeng
app and change the player shot to double shot style.Solution
Practice
fliping logic
, removing smali code
and jump instuction
in SMALI.