Conditional branches allow a program to choose between different execution paths. Loops build upon that concept by allowing a program to execute the same block of code repeatedly.
Without loops, programmers would have to manually duplicate instructions every time an operation needed to be performed multiple times.
For example, imagine we wanted to print the numbers 1 through 5:
printf("1\n");
printf("2\n");
printf("3\n");
printf("4\n");
printf("5\n");
This quickly becomes impractical. Instead, we can use a loop:
for (int i = 1; i <= 5; i++)
{
printf("%d\n", i);
}
Output:
1
2
3
4
5
Common loop types include:
for
Used when the number of iterations is known:
for (int i = 0; i < 10; i++)
{
printf("%d\n", i);
}
while
Used when execution should continue until a condition becomes false:
while (authenticated == false)
{
PromptForPassword();
}
do-while
Similar to a while loop, except the body executes at least once:
do
{
PromptForPassword();
}
while (authenticated == false);
Loops are extremely common throughout software. They are used to process arrays, handle network traffic, read files, parse data and perform repetitive tasks.
Loops at the Machine Level
Just like conditional branches, processors do not understand concepts such as for or while.
At a low level, a loop is typically implemented using three simple components:
- A counter or condition
- A comparison
- A jump back to an earlier instruction
Consider the following code:
for (int i = 0; i < 3; i++)
{
DoWork();
}
Conceptually, the CPU may perform something similar to:
mov eax, 0 ; set "eax" equal to "0"
LoopStart: ; this is just a label, used by "jmp" actions
call DoWork ; calls a function (will be explained in next class)
inc eax ; increase "eax" with "1", this is called "incrementation"
cmp eax, 3 ; compare "eax" with "3"
jl LoopStart ; jump if its less
Visually:
Start
│
▼
Do Work
│
▼
Increment i
│
▼
i < 3 ?
│ │
Yes No
│ │
│ └──►End
│
▼
Loop Back
The key observation is that loops are simply conditional branches that repeatedly jump to an earlier location in the program.
This concept appears everywhere in reverse engineering. When examining assembly code, you will frequently encounter loops implemented through comparisons and jump instructions rather than high-level constructs such as for and while.
Understanding this relationship makes it much easier to read disassembly and reason about how software behaves internally.