FizzBuzz/Assembly: Difference between revisions

Content added Content deleted
(360 Assembly)
(moved 6502 / 68000 / 8086 Assembly)
Line 88: Line 88:
SAVE DS 18F
SAVE DS 18F
END HELLO </lang>
END HELLO </lang>


=={{header|6502 Assembly}}==
The modulus operation is rather expensive on the 6502,
so a simple counter solution was chosen.
<lang> .lf fzbz6502.lst
.cr 6502
.tf fzbz6502.obj,ap1
;------------------------------------------------------
; FizzBuzz for the 6502 by barrym95838 2013.04.04
; Thanks to sbprojects.com for a very nice assembler!
; The target for this assembly is an Apple II with
; mixed-case output capabilities and Applesoft
; BASIC in ROM (or language card)
; Tested and verified on AppleWin 1.20.0.0
;------------------------------------------------------
; Constant Section
;
FizzCt = 3 ;Fizz Counter (must be < 255)
BuzzCt = 5 ;Buzz Counter (must be < 255)
Lower = 1 ;Loop start value (must be 1)
Upper = 100 ;Loop end value (must be < 255)
CharOut = $fded ;Specific to the Apple II
IntOut = $ed24 ;Specific to ROM Applesoft
;======================================================
.or $0f00
;------------------------------------------------------
; The main program
;
main ldx #Lower ;init LoopCt
lda #FizzCt
sta Fizz ;init FizzCt
lda #BuzzCt
sta Buzz ;init BuzzCt
next ldy #0 ;reset string pointer (y)
dec Fizz ;LoopCt mod FizzCt == 0?
bne noFizz ; yes:
lda #FizzCt
sta Fizz ; restore FizzCt
ldy #sFizz-str ; point y to "Fizz"
jsr puts ; output "Fizz"
noFizz dec Buzz ;LoopCt mod BuzzCt == 0?
bne noBuzz ; yes:
lda #BuzzCt
sta Buzz ; restore BuzzCt
ldy #sBuzz-str ; point y to "Buzz"
jsr puts ; output "Buzz"
noBuzz dey ;any output yet this cycle?
bpl noInt ; no:
txa ; save LoopCt
pha
lda #0 ; set up regs for IntOut
jsr IntOut ; output itoa(LoopCt)
pla
tax ; restore LoopCt
noInt ldy #sNL-str
jsr puts ;output "\n"
inx ;increment LoopCt
cpx #Upper+1 ;LoopCt >= Upper+1?
bcc next ; no: loop back
rts ; yes: end main
;------------------------------------------------------
; Output zero-terminated string @ (str+y)
; (Entry point is puts, not outch)
;
outch jsr CharOut ;output string char
iny ;advance string ptr
puts lda str,y ;get a string char
bne outch ;output and loop if non-zero
rts ;return
;------------------------------------------------------
; String literals (in '+128' ascii, Apple II style)
;
str: ; string base offset
sFizz .az -"Fizz"
sBuzz .az -"Buzz"
sNL .az -#13
;------------------------------------------------------
; Variable Section
;
Fizz .da #0
Buzz .da #0
;------------------------------------------------------
.en </lang>

=={{header|68000 Assembly}}==
This implementation uses two counters instead of divisions for the moduli.
<lang 68000devpac>;
; FizzBuzz for Motorola 68000 under AmigaOs 2+ by Thorham
;
; Uses counters instead of divisions.
;
_LVOOpenLibrary equ -552
_LVOCloseLibrary equ -414
_LVOVPrintf equ -954

execBase=4

start
move.l execBase,a6

lea dosName,a1
moveq #36,d0
jsr _LVOOpenLibrary(a6)
move.l d0,dosBase
beq exit

move.l dosBase,a6
lea counter,a2

moveq #3,d3 ; fizz counter
moveq #5,d4 ; buzz counter

moveq #1,d7
.loop
clr.l d5

; fizz
subq.l #1,d3
bne .noFizz
moveq #1,d5
moveq #3,d3
move.l #fizz,d1
clr.l d2
jsr _LVOVPrintf(a6)
.noFizz

; buzz
subq.l #1,d4
bne .noBuzz
moveq #1,d5
moveq #5,d4
move.l #buzz,d1
clr.l d2
jsr _LVOVPrintf(a6)
.noBuzz

; number
tst.l d5
bne .noNumber
move.l d7,(a2)
move.l #number,d1
move.l a2,d2
jsr _LVOVPrintf(a6)

.noNumber
move.l #newLine,d1
clr.l d2
jsr _LVOVPrintf(a6)

addq.l #1,d7
cmp.l #100,d7
ble .loop

exit
move.l execBase,a6
move.l dosBase,a1
jsr _LVOCloseLibrary(a6)
rts
;
; variables
;
dosBase
dc.l 0

counter
dc.l 0
;
; strings
;
dosName
dc.b "dos.library",0

newLine
dc.b 10,0

number
dc.b "%ld",0

fizz
dc.b "Fizz",0

buzz
dc.b "Buzz",0</lang>

=={{header|8086 Assembly}}==
Assembly programs that output a number on the screen are programmable in two ways: calculating the number in binary to convert it next in ASCII for output,
or keeping the number in Binary Coded Decimal (BCD) notation
to speed up the output to the screen, because
no binary to decimal conversion needs to be applied. <br>
The first approach is the most useful because the binary number
is immediately recognizable to the computer, but, in a problem
where the calculations are very few and simple and the final result
is mainly text on the screen, using binary numbers would speed up
calculations, but will greatly slow down the output.

The BCD used is based on the ASCII text encoding:
zero is the hexadecimal byte 30, and nine is the hexadecimal byte 39. <br>
The BCD number is kept in the DX register,
the most significant digit in DH and the less significant digit in DL. <br>
See the comments for further explaining of the program's structure,
which is meant for speed and compactness rather than modularity:
there are no subroutines reusable in another program without being edited.

This program is 102 bytes big when assembled.
The program is written to be run in an IBM PC because the 8086 processor
alone does not provide circuitry for any kind of direct screen output.

At least, I should point out that this program is a little bugged:
the biggest number representable with the BCD system chosen is 99,
but the last number displayed is 100, which would be written as :0
because the program does provide overflow detecting only for the units,
not for tens (39 hex + 1 is 3A, that is the colon symbol in ASCII). <br>
However, this bug is hidden by the fact that the number 100
is a multiple of five, so the number is never displayed,
because it is replaced by the string "buzz".
<lang asm> ; Init the registers
mov dx,03030h ; For easier printing, the number is
;kept in Binary Coded Decimal, in
----

;the DX register.
mov ah,0Eh ; 0Eh is the IBM PC interrupt 10h
;function that does write text on
;the screen in teletype mode.
mov bl,100d ; BL is the counter (100 numbers).
xor cx,cx ; CX is a counter that will be used
;for screen printing.
xor bh,bh ; BH is the counter for counting
;multiples of three.

writeloop: ; Increment the BCD number in DX.
inc dl ; Increment the low digit
cmp dl,3Ah ; If it does not overflow nine,
jnz writeloop1 ;continue with the program,
mov dl,30h ;otherwise reset it to zero and
inc dh ;increment the high digit
writeloop1:
inc bh ; Increment the BH counter.
cmp bh,03h ; If it reached three, we did
;increment the number three times
;from the last time the number was
;a multiple of three, so the number
;is now a multiple of three now,
jz writefizz ;then we need to write "fizz" on the
;screen.
cmp dl,30h ; The number isn't a multiple of
jz writebuzz ;three, so we check if it's a
cmp dl,35h ;multiple of five. If it is, we
jz writebuzz ;need to write "buzz". The program
;checks if the last digit is zero or
;five.
mov al,dh ; If we're here, there's no need to
int 10h ;write neither "fizz" nor "buzz", so
mov al,dl ;the program writes the BCD number
int 10h ;in DX
writespace:
mov al,020h ;and a white space.
int 10h
dec bl ; Loop if we didn't process 100
jnz writeloop ;numbers.

programend: ; When we did reach 100 numbers,
cli ;the program flow falls here, where
hlt ;interrupts are cleared and the
jmp programend ;program is stopped.

writefizz: ; There's need to write "fizz":
mov si,offset fizz ; SI points to the "fizz" string,
call write ;that is written on the screen.
xor bh,bh ; BH, the counter for computing the
;multiples of three, is cleared.
cmp dl,30h ; We did write "fizz", but, if the
jz writebuzz ;number is a multiple of five, we
cmp dl,35h ;could need to write "buzz" also:
jnz writespace ;check if the number is multiple of
;five. If not, write a space and
;return to the main loop.
writebuzz: ; (The above code falls here if
;the last digit is five, otherwise
;it jumps)
mov si,offset buzz ;SI points to the "buzz" string,
call write ;that is written on the screen.
jmp writespace ; Write a space to return to the main
;loop.

write: ; Write subroutine:
mov cl,04h ; Set CX to the lenght of the string:
;both strings are 4 bytes long.
write1:
mov al,[si] ; Load the character to write in AL.
inc si ; Increment the counter SI.
int 10h ; Call interrupt 10h, function 0Eh to
;write the character and advance the
;text cursor (teletype mode)
loop write1 ; Decrement CX: if CX is not zero, do
ret ;loop, otherwise return from
;subroutine.

fizz: ;The "fizz" string.
db "fizz"

buzz: ;The "buzz" string.
db "buzz"</lang>