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.
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:
goto statement in C/C++ and the jmp statement in assembly language.if and else statements in C/C++ and the branch-if statement in assembly language.switch statement in C/C++ and the select statement in Ada are examples of switch statements.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.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.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
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");
}
}
# 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
How switch statement can be based on a String? In Java, a switch on a string can be implemented using the
String.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.
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.
| 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 |