mirror of
https://github.com/michaelcmartin/Ophis.git
synced 2024-12-27 06:29:16 +00:00
214 lines
3.2 KiB
Plaintext
214 lines
3.2 KiB
Plaintext
.include "../platform/c64_0.oph"
|
|
.require "../platform/c64kernal.oph"
|
|
.outfile "fibonacci.prg"
|
|
|
|
lda #<opening ; Print opening text
|
|
sta fun'args
|
|
lda #>opening
|
|
sta fun'args+1
|
|
jsr print'string
|
|
|
|
lda #$00
|
|
sta fun'vars ; Count num from 0 to 19
|
|
* lda fun'vars ; Main loop: print num, with leading space if <10
|
|
cmp #$09
|
|
bcs +
|
|
lda #$20
|
|
jsr chrout
|
|
lda fun'vars
|
|
* sta fun'args ; Copy num to args, print it, plus ": "
|
|
inc fun'args
|
|
lda #$00
|
|
sta fun'args+1
|
|
jsr print'dec
|
|
lda #$3A
|
|
jsr chrout
|
|
lda #$20
|
|
jsr chrout
|
|
lda fun'vars ; Copy num to args, call fib, print result
|
|
sta fun'args
|
|
jsr fib
|
|
jsr print'dec
|
|
lda #$0D ; Newline
|
|
jsr chrout
|
|
inc fun'vars ; Increment num; if it's 20, we're done.
|
|
lda fun'vars
|
|
cmp #20
|
|
bne -- ; Otherwise, loop.
|
|
rts
|
|
|
|
opening:
|
|
.byte 147, " FIBONACCI SEQUENCE",13,13,0
|
|
|
|
.scope
|
|
; Uint16 fib (Uint8 x): compute Xth fibonnaci number.
|
|
; fib(0) = fib(1) = 1.
|
|
; Stack usage: 3.
|
|
|
|
fib: lda #$03
|
|
jsr save'stack
|
|
|
|
lda fun'vars ; If x < 2, goto _base.
|
|
cmp #$02
|
|
bcc _base
|
|
|
|
dec fun'args ; Otherwise, call fib(x-1)...
|
|
jsr fib
|
|
lda fun'args ; Copy the result to local variable...
|
|
sta fun'vars+1
|
|
lda fun'args+1
|
|
sta fun'vars+2
|
|
lda fun'vars ; Call fib(x-2)...
|
|
sec
|
|
sbc #$02
|
|
sta fun'args
|
|
jsr fib
|
|
clc ; And add the old result to it, leaving it
|
|
lda fun'args ; in the 'result' location.
|
|
adc fun'vars+1
|
|
sta fun'args
|
|
lda fun'args+1
|
|
adc fun'vars+2
|
|
sta fun'args+1
|
|
jmp _done ; and then we're done.
|
|
|
|
_base: ldy #$01 ; In the base case, just copy 1 to the
|
|
sty fun'args ; result.
|
|
dey
|
|
sty fun'args+1
|
|
|
|
_done: lda #$03
|
|
jsr restore'stack
|
|
rts
|
|
.scend
|
|
|
|
.scope
|
|
; Stack routines: init'stack, save'stack, restore'stack
|
|
.data zp
|
|
.space _sp $02
|
|
.space _counter $01
|
|
.space fun'args $10
|
|
.space fun'vars $40
|
|
|
|
.text
|
|
init'stack:
|
|
lda #$00
|
|
sta _sp
|
|
lda #$A0
|
|
sta _sp+1
|
|
rts
|
|
|
|
save'stack:
|
|
sta _counter
|
|
sec
|
|
lda _sp
|
|
sbc _counter
|
|
sta _sp
|
|
lda _sp+1
|
|
sbc #$00
|
|
sta _sp+1
|
|
ldy #$00
|
|
* lda fun'vars, y
|
|
sta (_sp), y
|
|
lda fun'args, y
|
|
sta fun'vars, y
|
|
iny
|
|
dec _counter
|
|
bne -
|
|
rts
|
|
|
|
restore'stack:
|
|
pha
|
|
sta _counter
|
|
ldy #$00
|
|
* lda (_sp), y
|
|
sta fun'vars, y
|
|
iny
|
|
dec _counter
|
|
bne -
|
|
pla
|
|
clc
|
|
adc _sp
|
|
sta _sp
|
|
lda _sp+1
|
|
adc #$00
|
|
sta _sp+1
|
|
rts
|
|
.scend
|
|
|
|
|
|
; Utility functions. print'dec prints an unsigned 16-bit integer.
|
|
; It's ugly and long, mainly because we don't bother with niceties
|
|
; like "division". print'string prints a zero-terminated string.
|
|
|
|
.scope
|
|
.data
|
|
.org fun'args
|
|
.space _val 2
|
|
.space _step 2
|
|
.space _res 1
|
|
.space _allowzero 1
|
|
.text
|
|
print'dec:
|
|
lda #$00
|
|
sta _allowzero
|
|
lda #<10000
|
|
sta _step
|
|
lda #>10000
|
|
sta _step+1
|
|
jsr repsub'16
|
|
lda #<1000
|
|
sta _step
|
|
lda #>1000
|
|
sta _step+1
|
|
jsr repsub'16
|
|
lda #0
|
|
sta _step+1
|
|
lda #100
|
|
sta _step
|
|
jsr repsub'16
|
|
lda #10
|
|
sta _step
|
|
jsr repsub'16
|
|
lda _val
|
|
jsr _print
|
|
rts
|
|
|
|
repsub'16:
|
|
lda #$00
|
|
sta _res
|
|
* lda _val
|
|
sec
|
|
sbc _step
|
|
lda _val+1
|
|
sbc _step+1
|
|
bcc _done
|
|
lda _val
|
|
sec
|
|
sbc _step
|
|
sta _val
|
|
lda _val+1
|
|
sbc _step+1
|
|
sta _val+1
|
|
inc _res
|
|
jmp -
|
|
_done: lda _res
|
|
ora _allowzero
|
|
beq _ret
|
|
sta _allowzero
|
|
lda _res
|
|
_print: clc
|
|
adc #'0
|
|
jsr chrout
|
|
_ret: rts
|
|
.scend
|
|
|
|
print'string:
|
|
ldy #$00
|
|
* lda (fun'args), y
|
|
beq +
|
|
jsr chrout
|
|
iny
|
|
jmp -
|
|
* rts
|