#Use local labels

All of your labels are global labels.

Since all these labels are trying to complete the same task and they all work together, they should all be grouped under a single global variable, and have the rest of the labels be local.

For example, you would change this label:

 fizzbuzz_check:

to:

 .fizzbuzz_check:

Also, it's just better practice.

<hr>

#Different conditional jump

At the end of each check for either Fizz, Buzz, or FizzBuzz, you do something like this:

 je print_fizzbuzz ; if so, proceed with printing

 jmp fizz_check ; if not, try checking for fizz

 print_fizzbuzz:

This could be shortened to:

 jne main_loop

 print_fizzbuzz:

If the `jne` doesn't pass, execution will fall through to `print_fizzbuzz`

<hr>

#Versatility

Right now, your code only supports Fizz, Buzz, and Fizzbuzz.

But what if you wanted to change things up a bit? Say you wanted to say "Fizz" every fourth number?

To do this, you'd be adding quite a chunk of code.

Although, there is an easier way to do this; use `struc`s.

Say you created this `struc`:

 struc message
 
 .say: resb 10
 .num: resb 1
 
 endstruc

You could then do something create a bunch of messages easily like this:

 messages:
 db "FizzBuzz", 0, 0
 db 15

 db "Buzz",0,0,0,0,0,0
 db 5

 db "Fizz",0,0,0,0,0,0
 db 3

 db 0,0,0,0,0,0,0,0,0,0; so, when iterating, can know if the end has been reached
 db 0

(The extra 0's are for filling up the 10 bytes given for the name)
(Note the order: you want greatest to least)

And, you can easily 

Now, in your main code, you can easily iterate through `messages` and, if the counter is evenly divisible by the value in the `num` field, then you log the `say` field.


Now, the code could be written like this:

 xor cx, cx
 
 main_loop:
 	inc cx
 	cmp cx, 100
 
 	jg .done
 
 	call search
 
 	jmp main_loop
 
 .done:
 	.EXIT
 
 search:
 	mov si, messages
 
 .next:
 	mov ax, cx
 	mov bh, [si + message.num]; divisor
 	div bh
 
 	cmp ah, 0; was evenly divisible
 	je .print_message
 
 	add si, message_size
 	cmp byte [si], 0; the next item in `messages` is the terminator
 	jne .next
 
 	jmp .print_num
 
 .print_message:
 	PutStr [si + message.say]
 	nwln
 	ret
 	
 .print_num:
 	PutInt cx
 	nwln
 	ret

*Note: This was troublesome to test out without `macros.s` so if there are any issues, notify me*