1

I'm writing a simple for loop using the FASM assembler. But when I run it, it runs as an infinite loop.
What is the issue?

format ELF64 executable 3
segment readable executable
entry main

main:
        mov ax, 8
        jmp .loop
.loop:
        cmp ax, 0
        je .exit
        mov edx,11     ;message length
        mov ecx,msg     ;message to write
        mov ebx,1       ;file descriptor (stdout)
        mov eax,4
        sub ax, 1
        jmp .loop
.exit:
        mov eax, 1
        int 0x80

segment readable writable
msg db  "Hello World", 10, 0
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
TM Ahad
  • 11
  • 1

2 Answers2

3

at the bottom of the loop you have

    mov eax,4
    sub ax, 1
    jmp .loop

so, set eax to 4, then subtract 1 from ax (which is the lower 16 bits of eax), which means ax (and eax) are both now 3. The cmp ax, 0 is always going to be not equal (for the je) after that.

Maybe you didn't realize that ax is just the lower half of eax?

Ryan Haining
  • 35,360
  • 15
  • 114
  • 174
2

Main error

mov eax,4
sub ax, 1

The 16-bit AX register that you are using to control the loop is part of the 32-bit EAX register that you are using for the function number of the write system call. You cannot have the same register do double duty, unless you take precautions like eg. preserving the existing value on the stack:

        mov ax, 8
        jmp .loop
.loop:
        cmp  ax, 0
        je   .exit
        PUSH EAX        ; PRESERVE AX
        mov  edx,11
        mov  ecx,msg
        mov  ebx,1
        mov  eax,4
        POP  EAX        ; RESTORE AX
        sub  ax, 1
        jmp  .loop
.exit:

The preferred solution however would be to use a different register to control the loop. You could choose ESI for it.

Some more errors

   jmp .loop
.loop:

This jmp is redundant as the execution can just as easily fall through.

   mov  edx,11

Normally, you would want to include the newline, so the length should become 12.

   mov  eax,4

To actually invoke write, you still have to insert an int 0x80 instruction.

   cmp  ax, 0
   je   .exit

   sub  ax, 1
   jmp  .loop
.exit:

It is much better to test for zero near the bottom of the loop:

New loop

        mov  esi, 8
.loop:
        mov  edx, 12
        mov  ecx, msg
        mov  ebx, 1
        mov  eax, 4
        int  0x80
        dec  esi
        jnz  .loop

        xor  ebx, ebx
        mov  eax, 1
        int  0x80
Sep Roland
  • 33,889
  • 7
  • 43
  • 76