Wishful Coding

Didn't you ever wish your computer understood you?

Branch-free FizzBuzz in Assembly

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
Pepijn de Vos