I came across this post that discusses ways to write FizzBuzz in Clojure without using conditionals. However, most if not all of the solutions still do a lot of branching behind the scenes. Think of hash lookups for example.
So I asked to myself, how can I write a FizzBuzz solution with no branches at all? Probably not in Clojure; you can’t easily tell where it is branching or not.
The only way to be absolutely sure is to write it in assembly. So I did. I never did assembly before, so it might be terrible code.
I used an array of 15 pointers to either “fizz”, “buzz”, “fizzbuzz”, or a number buffer. I then filled the number buffer with the current number in ascii and printed whatever I get from the array.
One thing I struggeled with is how to stop.
At first I had one condition to see if I reached 100.
Now I use a lookup table that calls sys_time
99 times and then sys_exit
.
section .data
f db "fizz "
b db "buzz "
fb db "fizzbuzz"
n db 10 ; newline string
cycle dq num, num, f, num, b, f, num, num, f, b, num, f, num, num, fb
callid dq 13, 1 ; sys_time, sys_exit
section .bss
num resb 8 ; number buffer
section .text
global _start
print: ;write rcx
mov rax,4 ;sys_write
mov rbx,1 ;stdout
mov rdx,8
int 0x80
ret
newline: ;write newline
mov rax,4 ;sys_write
mov rbx,1 ;stdout
mov rcx,n
mov rdx,1
int 0x80
ret
itoa: ;convert rax to str
mov byte[num+1],0x30
mov rdx,0
mov rcx,10
div rcx
add [num+1],rdx
mov byte[num],0x30
mov rdx,0
mov rcx,10
div rcx
add [num],rdx
ret
_start:
mov r12,0
hundredtimes:
; initialise number buffer
mov rax,r12
inc rax
call itoa
; mod 15 the number
mov rax,r12
mov rdx,0
mov rcx,15
div rcx
; look up the number in cycle
; prints the num buffer or any of the strings
mov rcx,[cycle+rdx*8]
call print
call newline
; next...
inc r12
; devide the number by 100
mov rax,r12
mov rdx,0
mov rcx,100
div rcx
; get the time or exit
mov rax,[callid+rax*8]
int 0x80
; jump to the top of the loop
jmp hundredtimes
To compile on a 64 bit machine:
nasm -f elf64 fizzbuzz.asm
ld -o fb fizzbuzz.o
./fb