Assembly Language - Loop Structures
Loops are one of the most common control structures in programming. In assembly language, you can use the LOOP instruction or conditional jumps to implement various loop logic. * * *The LOOP Instruction
LOOP is an x86 instruction specifically designed for loops, using ECX as a counter:
Each time LOOP is executed, ECX is automatically decremented by 1. If ECX is not 0, it jumps to the target label.
Example
; File path: loop_basic.asm
; Basic usage of LOOP instruction: repeat output 5 times
section.data
msg db'tutorial',0xA
len equ$- msg
section.text
global _start
_start:
mov ecx,5; Loop counter = 5 (loop 5 times)
repeat:
; Save ecx (system call might modify it)
push ecx
; Output msg
mov eax,4
mov ebx,1
mov ecx, msg
mov edx, len
int 0x80
; Restore ecx
pop ecx
loop repeat ; ecx--; if ecx != 0 jump to repeat
mov eax,1
mov ebx,0
int 0x80
Running result:
$ nasm -f elf32 loop_basic.asm -o loop_basic.o $ ld -m elf_i386 loop_basic.o -o loop_basic $ ./loop_basic tutorial tutorial tutorial tutorial tutorial
* * *
loopuses ECX (32-bit) as the counter by default. In 16-bit mode, CX is used; in 64-bit mode, RCX is used. Make sure to set the value of ECX correctly before the loop.
LOOP Variants
| Instruction | Jump Condition | Description |
|---|---|---|
| LOOP | ECX != 0 | Standard loop, decrements ECX first then checks |
| LOOPE / LOOPZ | ECX != 0 and ZF = 1 | Continue loop if equal |
| LOOPNE / LOOPNZ | ECX != 0 and ZF = 0 | Continue loop if not equal |
Example
; LOOPE example: find the first non-zero value in an array
section.data
array db 0,0,0,5,0,0; First three are 0, fourth is 5
section.text
global _start
_start:
mov ecx,6; Array length
mov esi, array -1; Point to one position before the array
find_nonzero:
inc esi; Move to the next element
cmp byte,0; Current element == 0 ?
loope find_nonzero ; If it is 0 and ecx > 0, continue looping
; Loop ended: found the first non-zero element, or traversal finished
; esi now points to the address of the first non-zero element
; ecx contains the number of remaining uncompared elements
mov eax,1
mov ebx,0
int 0x80
* * *
Conditional Loops (WHILE Loops)
Implementing a while loop with conditional jumps: check the condition first, then execute the loop body.Example
; File path: while_loop.asm
; Implementation: while (x < 100) x = x * 2;
section.data
x dd 1
limit dd 100
section.text
global _start
_start:
; while loop
while_start:
mov eax,; Load x
cmp eax,; x < 100 ?
jge while_end ; If x >= 100, end loop
shl eax,1; x = x * 2
mov,eax; Store back to x
jmp while_start ; Go back to the start of the loop, re-check condition
while_end:
; x is now 128 (1->2->4->8->16->32->64->128, 128 >= 100 stop)
mov eax,1
mov ebx,; Return x as exit code
int 0x80
* * *
DO-WHILE Loop
Execute the loop body first, then check the condition:Example
; DO-WHILE loop: execute at least once
section.data
counter dd 0
section.text
global _start
_start:
mov dword,0
do_loop:
; Loop body: counter++ (executes at least once)
inc dword
; Check condition
cmp dword,5
jl do_loop ; Continue when counter < 5
; counter finally = 5
mov eax,1
mov ebx,0
int 0x80
* * *
Nested Loops
Nested loops require saving the outer loop counter:Example
; File path: nested_loop.asm
; Nested loop example: print multiplication table (3Γ3)
section.data
space db' '
newline db 0xA
; Used to store converted number characters (2 digits + space + null)
num_str db' ',0
section.text
global _start
_start:
mov ecx,3; Outer loop counter (number of rows)
outer_loop:
push ecx; β
Save outer counter! (Important)
mov ecx,3; Inner loop counter (number of columns)
inner_loop:
push ecx; Save inner counter
; Calculate product = outer row number(4-current ecx) Γ inner column number
; Specific number conversion output is omitted here, only demonstrating structure
; Actual output: row number Γ column number
pop ecx; Restore inner counter
loop inner_loop ; Inner loop
; Output newline
mov eax,4
mov ebx,1
mov ecx, newline
mov edx,1
int 0x80
pop ecx; β
Restore outer counter
loop outer_loop ; Outer loop
mov eax,1
mov ebx,0
int 0x80
* * *The most common mistake in nested loops is forgetting to save the outer counter's value on the stack. LOOP modifies ECX; when you reset ECX in the inner loop, the outer count value is lost. The solution is to
push ecxbefore entering the inner loop andpop ecxafter leaving it.
Loop Optimization Tips
Some methods to improve loop efficiency:Example
; Loop optimization comparison
; Method A: Using LOOP instruction (slower, but not obvious)
mov ecx,1000
loop_a:
add eax,
add ebx,4
loop loop_a
; Method B: Using conditional jump (manual counting) (usually faster)
mov ecx,1000
loop_b:
add eax,
add ebx,4
dec ecx
jnz loop_b
; Method C: Loop unrolling (fastest, but larger code size)
; Unroll 1000 iterations into processing 4 elements per iteration
mov ecx,250; 1000 / 4 = 250
loop_unrolled:
add eax,
add eax,[ebx+4]
add eax,[ebx+8]
add eax,[ebx+12]
add ebx,16
dec ecx
jnz loop_unrolled
; Method D: Counting down (reduces comparison instructions)
mov ecx,1000
lea ebx,[array +1000*4-4]; Start from the end of the array
loop_reverse:
add eax,
sub ebx,4
dec ecx
jnz loop_reverse
* * *
Complete Example: Calculate the Sum of 1 to 100
Example
; File path: sum_1_to_100.asm
; Calculate 1+2+...+100 = 5050
section.data
msg db'Sum of 1 to 100 is: '
msg_len equ$- msg
newline db 0xA
section.bss
result_str resb 12; Store the converted number string
section.text
global _start
_start:
; Calculate cumulative sum
mov ecx,100; Loop 100 times
mov eax,0; Initial cumulative sum is 0
mov ebx,1; Current number to add
sum_loop:
add eax,ebx; eax += ebx
inc ebx; Next number
loop sum_loop ; Continue loop
; eax = 5050
; Output prompt text
push eax; Save result
mov eax,4
mov ebx,1
mov ecx, msg
mov edx, msg_len
int 0x80
pop eax; Restore result
; Convert number to string (simple version: output integer value directly)
; Simplified processing here, convert the low byte of eax to character
add al,'0'; Inaccurate, for demonstration only
mov,al
; Output result
mov eax,4
mov ebx,
YouTip