Okay, finally got the issues sorted out. The following is code for Kowalski's 6502 assembler/simulator:
Code:
.ORG $1000
; Macros
printbcd .macro ; Print a byte in A as a pair of BCD digits
pha ; Save the value for later
lsr ; Isolate the high nybble and print it first
lsr
lsr
lsr
ora #$30 ; Turn the isolated digit into its ASCII character
printchar ; Print the character
pla ; Retrieve the original value
and #$0f ; Isolate the low nybble
ora #$30 ; Make it ASCII
printchar ; Print it
.endm
printchar .macro ; Print the character in A as an ASCII value
; do whatever here
sta $e001
.ENDM
; Fibonacci algorithm - calculates numbers up to 510 digits in BCD form
; a = 1
; b = 1
; print a
; a = a + b
; print b
; b = b + a
init ; Initialize buffers to 0000[...]1
ldx #$01
stx bufa
stx bufb
lda #$00
.l sta bufa,x
sta bufb,x
inx
bne .l
ldy #$01 ; Initialize the maximum-length counter
loop txa ; Check - is X zero?
beq pashort ; If so, cut the print loop short
printa ; Print buffer A as BCD values, one byte (2 digits) at a time
lda bufa,x ; X should be left pointing to the current MSB
printbcd ; Print it as a BCD pair
dex ; Drop down to the next most significant byte
bne printa
pashort lda bufa,x ; Get and print the LSB since the loop ends early
printbcd
LDA #$20 ; Print a space
printchar
; Note: SED and CLD could be moved out of the loop if decimal mode
; won't affect any other code (i.e. character printing,) but it's a
; negligible difference anyway.
sed ; Prep for BCD addition
clc
LDX #$ff ; Set X to $FF
addb2a ; Add buffer B to A as BCD values
inx
lda bufa,x ; Get the current byte from A
adc bufb,x ; Add the current byte from B
STA bufa,x ; Store it back to A
DEY ; Decrement the maximum-length counter
bne addb2a ; If it's > 0, go to the next byte
iny ; If it's 0, reset it for the next iteration just in case
BCS addb2a ; If we carried out, go to the next byte
cld ; Leave decimal mode
TXA ; Update the maximum-length counter
TAY
INY
cpx #$ff ; Did we run to the end of the buffer?
beq done ; If so, we're done here
TXA ; Check - is X zero?
beq pbshort ; If so, cut the print loop short
printb ; Print buffer B as BCD values, one byte (2 digits) at a time
lda bufb,x ; X should be left pointing to the current MSB
printbcd ; Print it as a BCD pair
dex ; Drop down to the next most significant byte
bne printb
pbshort lda bufb,x ; Get and print the LSB since the loop ends early
printbcd
; Note: SED and CLD could be moved out of the loop if decimal mode
; won't affect any other code (i.e. character printing,) but it's a
; negligible difference anyway.
sed ; Prep for BCD addition
clc
ldx #$ff ; Set X to $FF
adda2b ; Add buffer A to B as BCD values
inx
lda bufb,x ; Get the current byte from A
adc bufa,x ; Add the current byte from B
STA bufb,x ; Store it back to A
DEY ; Decrement the maximum-length counter
BNE adda2b ; If it's > 0, go to the next byte
iny ; If it's 0, reset it for the next iteration just in case
BCS adda2b ; If we carried out, go to the next byte
cld ; Leave decimal mode
TXA ; Update the maximum-length counter
TAY
INY
cpx #$ff ; Did we run to the end of the buffer?
beq done ; If so, we're done here
LDA #$20 ; Print a space
printchar
JMP loop ; If we're not done, continue
done ; If we are done, finish
brk
; Buffers
bufa .set $2000
bufb .set $2100
It's not super-pretty and I haven't double-checked the exit conditions to ensure that it will quit properly with no erroneous output when the bignum size runs up to a full page. It also uses the simulator's output facility for cheap printing, but I did at least implement my own BCD-to-ASCII conversion in an attempt to be fair about it. Anyway, assuming a 1MHz test system, when run up to just shy of 15,000,000 cycles it produces the following number:
Code:
0669260914144474
2383972451046333
4341778432843725
1805687861613243
9625858202478278
9140698057971348
5513550524628221
6604878690798813
8893035851040403
0806030527298628
6853890899496037
8909866230416986
5421475796599705
5876430614925437
1892863787317305
7897731694551328
7392301441138267
0293400725105488
1903535683969679
7453359616023179
7925656175919745
2805998203167417
9044885601740086
7886789122530726
0989620372623122
3715318210405157
8714172040612830
4969924233370562
76562264
Which, according to
this calculator, is the correct value for Fib(2178) - so yes, a bit over 2,000 Fibonacci numbers.