%define COUNT    20
[bits 16]
[org  0x7c00]
start:
    cli
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov ax, 0x9c00
    mov sp, ax
    mov cx, COUNT
    sti
fizzbuzz:
    .printnumber:
        mov  ax, cx
        call putword
    .test3:
        mov ax, cx
        mov dh, 3
        div dh
        or  ah, ah
        jz  .fizz
    .test5:
        mov ax, cx
        mov dh, 5
        div dh
        or  ah, ah
        jz  .buzz
        jmp .testcx
    .fizz:
        mov  si, fizz
        call putstr
        jmp  .test5
    .buzz:
        mov  si, buzz
        call putstr
    .testcx:
        mov  si, crlf
        call putstr
        or   cx, cx
        jz   hang
        dec  cx
        jmp  fizzbuzz
hang:
    cli
    hlt
    jmp $
putchar:
    mov ah, 0x0e
    int 0x10
    ret
putstr:
    .do_char:
        lodsb
        or   al, al
        jz   .done
        call putchar
        jmp  .do_char
    .done:
        ret
putnibble:
    cmp  al, 10
    jl   .lt10
    add  al, 'A' - 10
    call putchar
    jmp  .done
    .lt10:
        add  al,'0'
        call putchar
    .done:
        ret
putbyte:
    push ax
    shr  al, 4
    call putnibble
    pop  ax
    and  al, 0x0f
    call putnibble
    cmp  bx, 0
    je   .done
    mov  al, ' '
    call putchar
    .done:
        ret
putword:
    push bx
    push ax
    mov  al, ah
    mov  bx, 0
    call putbyte
    pop  ax
    mov  bx, 0
    call putbyte
    mov  al, ' '
    call putchar
    pop  bx
    ret
fizz:                db "fizz", 0
buzz:                db "buzz", 0
crlf:                db 13, 10, 0
times 510 - ($ - $$) db 0
                     dw 0xaa55
