Assembly Language - Loop Structures
Loops are one of the most common control structures in programs. In assembly language, you can use the LOOP instruction or conditional jumps to implement various loop logic.
LOOP Instruction
LOOPIt is an x86 instruction specially 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
; Basic usage of LOOP instruction: repeat output 5 times
section .data
msg db 'example', 0xA
len equ $ - msg
section .text
global _start
_start:
mov ecx, 5 ; Loop counter = 5 (loop 5 times)
repeat:
; Save ecx (system calls may 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
Output:
$ nasm -f elf32 loop_basic.asm -o loop_basic.o $ ld -m elf_i386 loop_basic.o -o loop_basic $ ./loop_basic example example example example example
loopBy default, ECX (32-bit) is used as the counter. In 16-bit mode, CX is used; in 64-bit mode, RCX is used. Be sure to set ECX correctly before the loop.
Variants of LOOP
| Instruction | Jump Condition | Description |
|---|---|---|
| LOOP | ECX != 0 | Standard loop: decrement ECX first, then test |
| LOOPE / LOOPZ | ECX != 0 and ZF = 1 | Continue loop if equal |
| LOOPNE / LOOPNZ | ECX != 0 and ZF = 0 | Continue loop if not equal |
Example
section .data
array db 0, 0, 0, 5, 0, 0 ; The first three are 0, the 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 [esi], 0 ; Is the current element == 0?
loope find_nonzero ; If it is 0 and ecx > 0, continue the loop
; Loop ends: found the first non-zero element, or finished traversal
; esi now points to the address of the first non-zero element
; ecx holds the number of elements not yet compared
mov eax, 1
mov ebx, 0
int 0x80
Conditional Loop (WHILE Loop)
Use conditional jumps to implement a while loop: test the condition first, then execute the loop body.
Example
; Implements: 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, [x] ; Load x
cmp eax, [limit] ; x < 100 ?
jge while_end ; If x >= 100, exit the loop
shl eax, 1 ; x = x * 2
mov [x], eax ; Store x back
jmp while_start ; Go back to loop start and re-test
while_end:
; x is now 128 (1->2->4->8->16->32->64->128, stops when 128 >= 100)
mov eax, 1
mov ebx, [x] ; Return x as the exit code
int 0x80
DO-WHILE Loop
Execute the loop body first, then test the condition:
Example
section .data
counter dd 0
section .text
global _start
_start:
mov dword [counter], 0
do_loop:
; Loop body: counter++ (executes at least once)
inc dword [counter]
; Test condition
cmp dword [counter], 5
jl do_loop ; Continue while counter < 5
; counter finally = 5
mov eax, 1
mov ebx, 0
int 0x80
Nested Loops
Nested loops require attention to saving the outer loop counter:
Example
; Nested loop example: print a multiplication table (3×3)
section .data
space db ' '
newline db 0xA
; Used to store the converted numeric characters (2 digits + space + null)
num_str db ' ', 0
section .text
global _start
_start:
mov ecx, 3 ; Outer loop counter (row count)
outer_loop:
push ecx ; ★ Save the outer loop counter! (Important)
mov ecx, 3 ; Inner loop counter (column count)
inner_loop:
push ecx ; Save the inner loop counter
; Calculate product = outer row number (4 - current ecx) × inner column number
; Specific number conversion output omitted here, only demonstrating the structure
; Actual output: row number × column number
pop ecx ; Restore the inner loop 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 the outer loop counter
loop outer_loop ; Outer loop
mov eax, 1
mov ebx, 0
int 0x80
The most common mistake in nested loops is forgetting to use the stack to save the outer loop counter's value. LOOP modifies ECX; when you reset ECX in the inner loop, the outer loop count is lost. The solution is to save it before each entry into the inner loop,
push ecxand restore it after leaving.pop ecx。
Loop Optimization Techniques
Some ways to improve loop efficiency:
Example
; Method A: Using LOOP instruction (slower, but not obvious)
mov ecx, 1000
loop_a:
add eax, [ebx]
add ebx, 4
loop loop_a
; Method B: Using conditional jump (manual counting) (usually faster)
mov ecx, 1000
loop_b:
add eax, [ebx]
add ebx, 4
dec ecx
jnz loop_b
; Method C: Loop unrolling (fastest, but large code size)
; Unroll a 1000-iteration loop to process 4 elements per iteration
mov ecx, 250 ; 1000 / 4 = 250
loop_unrolled:
add eax, [ebx]
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 compare instructions)
mov ecx, 1000
lea ebx, [array + 1000*4 - 4] ; Start from the end of the array
loop_reverse:
add eax, [ebx]
sub ebx, 4
dec ecx
jnz loop_reverse
Complete Example: Calculate the Sum from 1 to 100
Example
; 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 numeric string
section .text
global _start
_start:
; Calculate the cumulative sum
mov ecx, 100 ; Loop 100 times
mov eax, 0 ; Initial cumulative sum is 0
mov ebx, 1 ; The 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: directly output the integer value)
; Simplified here: convert the low byte of eax to a character
add al, '0' ; Not accurate, only for demonstration
mov [result_str], al
; Output result
mov eax, 4
mov ebx, 1
mov ecx, result_str
mov edx, 12
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, newline
mov edx, 1
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
Other extensionsConverting numbers to strings is a common problem in assembly. The simple method above only works when the number is 0-9. The complete number-to-string algorithm will be explained in detail in the "Number Processing" chapter.