For in Assembly Language

Assembly language doesn’t have high-level looping constructs like for loops. Instead, we use jumps and comparisons to create loops. Here’s an equivalent implementation of the various loop types in x86 assembly:

section .data
    fmt db "%d", 10, 0   ; Format string for printf

section .text
    global main
    extern printf

main:
    ; The most basic type, with a single condition
    mov ecx, 1           ; i := 1
loop1:
    cmp ecx, 3           ; i <= 3
    jg loop1_end
    push ecx
    push fmt
    call printf
    add esp, 8
    inc ecx              ; i = i + 1
    jmp loop1
loop1_end:

    ; A classic initial/condition/after loop
    mov ecx, 0           ; j := 0
loop2:
    cmp ecx, 3           ; j < 3
    jge loop2_end
    push ecx
    push fmt
    call printf
    add esp, 8
    inc ecx              ; j++
    jmp loop2
loop2_end:

    ; Range over an integer
    mov ecx, 0           ; i := 0
loop3:
    cmp ecx, 3           ; i < 3
    jge loop3_end
    push ecx
    push fmt
    call printf
    add esp, 8
    inc ecx
    jmp loop3
loop3_end:

    ; Infinite loop with break
    mov eax, 0
loop4:
    push eax
    push fmt
    call printf
    add esp, 8
    inc eax
    cmp eax, 1           ; Simulate 'break' after first iteration
    je loop4_end
    jmp loop4
loop4_end:

    ; Loop with continue
    mov ecx, 0           ; n := 0
loop5:
    cmp ecx, 6           ; n < 6
    jge loop5_end
    test ecx, 1          ; if n % 2 == 0
    jz loop5_continue
    push ecx
    push fmt
    call printf
    add esp, 8
loop5_continue:
    inc ecx
    jmp loop5
loop5_end:

    ret

This assembly code demonstrates various looping constructs equivalent to the original example:

  1. A basic loop with a single condition.
  2. A classic initial/condition/after loop.
  3. A loop that ranges over an integer.
  4. An “infinite” loop that breaks after one iteration.
  5. A loop that uses the concept of “continue” to skip even numbers.

Note that assembly language is much lower level than high-level languages. We have to manually manage the stack, call external functions (like printf), and use jumps and comparisons to control the flow of the program.

To run this program, you would need to assemble it into an object file, link it with the C library (for printf), and then execute the resulting binary. The exact commands may vary depending on your system and assembler, but it might look something like this:

$ nasm -f elf64 loops.asm
$ gcc -no-pie loops.o -o loops
$ ./loops
1
2
3
0
1
2
0
1
2
0
1
3
5

Remember that assembly language is highly dependent on the specific architecture and calling conventions of your system. This example is for x86 assembly and may need adjustments for other architectures or systems.