0

Im trying to make fizzbuzz in assembly x86 64 but i dont know how to make a loop that has conditional statements

I thought i would check for a condition and then jump to that procedure and then ret back. The problem is that if I return the label I will get a segfault for some reason.

The problem in the current code is that the fizzCondition will always execute

        mov ax, 6
        mov bl, 3
        div bl

        cmp ah, 0
        je fizzCondition

        ;check buzz condition etc..

        fizzCondition:
            mov eax, SYSWRITE
            mov edi, 1
            mov esi, fizz
            mov edx, 5
            syscall

        exit

if I do it like this I will get a segfault:

        mov ax, 6
        mov bl, 3
        div bl

        cmp ah, 0
        je fizzCondition

        exit

        fizzCondition:
            mov eax, SYSWRITE
            mov edi, 1
            mov esi, fizz
            mov edx, 5
            syscall

            ret
user259137
  • 85
  • 1
  • 1
  • As a rule of thumb, you can only `ret` from something you `call`. Either just jump back instead of `ret` or put a `call` in the conditional, for example by reversing the condition: `jne notFizzCondition; call fizzCondition; notFizzCondition: ...` – Jester Jun 02 '22 at 11:34
  • See also [What are callee and caller saved registers?](https://stackoverflow.com/a/56178078) re: your callee stepping on registers you use in the loop. See also [FizzBuzz in assembly - segmentation fault](https://stackoverflow.com/a/37494090) re: using down-counters instead of actually doing a slow `div` every iteration. My answer there has a semi-optimized FizzBuzz, storing strings into a buffer for fewer write syscalls. (The major factor in performance, much bigger than avoiding `div`.) – Peter Cordes Jun 02 '22 at 18:46

1 Answers1

1

You need to use a call instruction to call a function. The call instruction records the return address on the stack so the function you called can return. If you just jump to the function, it'll return to whatever is on the stack, causing a crash. So to fix your code, change it to read:

    mov ax, 6
    mov bl, 3
    div bl

    cmp ah, 0
    jne around
    call fizzCondition           ; this executes only when AH==0
  around:

    exit

    fizzCondition:
        mov eax, SYSWRITE
        mov edi, 1
        mov esi, fizz
        mov edx, 5
        syscall

        ret

Another thing you'll have to pay attention to is that there is only one set of registers. fizzCondition overwrites the registers eax, edi, esi, and edx so you'll need to save their contents somewhere (e.g. on the stack) if you want them to be preserved.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
fuz
  • 88,405
  • 25
  • 200
  • 352
  • so then in `around` i should do the buzz condition check? – user259137 Jun 02 '22 at 11:43
  • 1
    @user259137 The label `around` is just to have the condition inverted: we do the call if the condition is not “not-equal.” So yes, do the condition check right after. Note that labels just mark spots in the code. They are not containers or anything. There is no “in a label.” – fuz Jun 02 '22 at 12:13