	    .global	main
        .text
        .align	2

/*	FizzBuzz - a classic interview question.

    Count from 0 to n (let's make it 100).
    If the value is divisible by 3, print Fizz
    If the value is divisible by 5, print Buzz
    If the value is divisible by both 3 and 5, print FizzBuzz
    Otherwise, print the number.
*/

/*	Bible:

    x20		counter
    w21		bool that says whether or not I have printed anything
*/

/*	mod(a, b) - implements a % b
	a comes to us in x0
	b comes to us in x1
	method:
    integer divide a by b - for example - 5 % 3 
	    would need 5 // 3 yielding 1
    multiply result by b - 1 * 3 is 3
    subtract result from a - 5 - 3 yielding 2 
	    and that's our return value.
*/
mod:	sdiv 	x2, x0, x1				// x2 gets a // b
        msub	x0, x2, x1, x0			// x0 gets a - a // b * b	
        ret

main:	stp		x20, x30, [sp, -16]!
        str		x21, [sp, -16]!

        mov		x20, xzr
1:		cmp		x20, 100
        bge		99f

        mov		w21, wzr

        // Test for divisible by 3
        mov		x0, x20
        mov		x1, 3
        bl		mod
        cbnz	x0, 5f
        // If we get here, the counter was divisible by 3
        ldr		x0, =fizz
        bl		printf
        add		w21, w21, 1

5:		mov		x0, x20
        mov		x1, 5
        bl		mod
        cbnz	x0, 10f
        // If we get here, the counter was divisible by 5
        ldr		x0, =buzz
        bl		printf
        add		w21, w21, 1

10:		cbz 	w21, 20f
        // If we get here, it means that we have printed
        // something (either fizz, or buzz or fizzbuzz)
        // so all we need now is a new line
        ldr		x0, =nl
        bl		puts
        b 		80f

20:		// If we get here, the counter was neither a
        // multiple of 3 nor of 5. Therefore, we need
        // to print the counter itself.

        ldr		x0, =fmt
        mov		x1, x20
        bl 		printf

80:		add		x20, x20, 1
        b 		1b		


99:		ldr		x21, [sp], 16
        ldp		x20, x30, [sp], 16
        mov		w0, wzr
        ret

        .data
fizz:	.asciz	"Fizz"
buzz:	.asciz	"Buzz"
nl:		.asciz	""
fmt:	.asciz	"%ld\n"

        .end
