Search code examples
assemblyfizzbuzzyasm

FizzBuzz in assembly - segmentation fault


I am trying to write FizzBuzz in Assembly and I am seeing segmentation fault all the time. So far I have determined that it is not my printing routines (because I have removed their contents and the problem persists) and the error hides somewhere in the main function.

I was getting this output when I run the program:

fizzSegmentation fault

Leading me to believe that it's not the problem with using division and looking up the remainders. But I could be wrong, I haven't done Assembly in two years...

SECTION .data
global _start
    fizz: db "fizz", 4
    buzz: db "buzz", 4

SECTION .bss
    counter: resb    1

SECTION .text
_start:

    mov ax,0
    mov [counter],ax

main_loop:

    cmp ax,100          ;from 0 to 100
    je  exit            ;
    mov bl,3            ;divisor
    mov ah,0            ;here will be a remainder
    div bl              ;divide
    cmp ah,0            ;compare the remainder with 0
    je  print_fizz      ;print fizz if they equal
    mov bl,5            ;new divisor
    mov ah,0            ;do I have to do it every time?
    div bl              ;divide
    cmp ah,0            ;compare the remainder with 0
    je  print_buzz      ;print buzz if they equal
    jmp print_ax        ;print contents of ax if not
    inc ax              ;increment ax
    jmp main_loop       ;jump to label

print_ax:
    ret

print_fizz:
    ret

print_buzz:
    ret

exit:
    mov rax,1
    mov rbx,0
    int 80h
    ret

I am compiling using:

yasm -f elf64 -o fizzbuzz.o fizzbuzz.asm
ld -d -o fizzbuzz fizzbuzz.o

Solution

  • This is causing the segmentation fault:

    ...
        je  print_fizz      ;print fizz if they equal
    ...
        je  print_buzz      ;print buzz if they equal
        jmp print_ax        ;print contents of ax if not
    ...
    
    print_ax:
        ret
    
    print_fizz:
        ret
    
    print_buzz:
        ret
    ...
    

    Since you jump to the functions, the ret gets no return address and will return anywhere. Change it to a call/ret-pair:

    ...
    ;   je  print_fizz      ;print fizz if they equal
        jne .1              ;skip if not equal
        call print_fizz
        .1:
    ...
    
    ;   je  print_buzz      ;print buzz if they equal
        jne .2              ;skip if not equal
        call print_buzz
        .2:
    
    ;   jmp print_ax        ;print contents of ax if not
        call print_ax
    ...
    

    This will cause an infinite loop:

    mov ax,0
    mov [counter],ax
    
    main_loop:
    
        cmp ax,100          ;from 0 to 100
        je  exit
        ...
        mov ah,0            ;here will be a remainder
        div bl              ;divide
        ...
        mov ah,0            ;do I have to do it every time?
        div bl              ;divide
        ...
        inc ax              ;increment ax
        jmp main_loop       ;jump to label
    

    AX changes its values and is unfit to hold the loop-counter. I suggest:

    ...
    main_loop:
    
    ;   cmp ax,100          ;from 0 to 100
        cmp byte [counter], 100
    ...
    ;   inc ax              ;increment ax
        inc byte [counter]
        jmp main_loop       ;jump to label
    ...