; ; FIBONACCI80 ; ; calculate fibonacci numbers up to 10^80 ; calculation directly in video ram using screen code ; ; https://de.wikipedia.org/wiki/Fibonacci-Folge ; ;******************************************************************************* incasm "asm/c64.asm" ; print string to screen (PETSCII) ; PRINT string defm PRINT lda #/1 sta ptr_out+1 jsr printf endm ; print string to screen (PETSCII) at location X,Y ; PRINT_AT string, x, y defm PRINT_AT clc ldx #/3 ldy #/2 jsr kernal_plot ; set cursor lda #/1 sta ptr_out+1 jsr printf endm ; fill_block value, destination, count defm FILL_BLOCK lda #/2 sta ptr_out+1 lda #/3 sta size+1 lda #/1 jsr fill_mem endm ; way for any key if single != 'S' ; store key in single after waiting defm WAIT_ANY_KEY lda single cmp #"S" bne @end @wait jsr kernal_getin cmp #0 beq @wait sta single @end endm ; calculate FIB(x) using screen code ; s3 = s1 + s2 ; s1 address of most significant digit of first summand ; s2 address of most significant digit of second summand ; CALC_FIB s1, s2, s3 defm CALC_FIB ldy #79 ldx cnt clc @loop lda /1,y adc /2,y cmp #106 ; 2*'0' + 10, screen code bcs @overflow ; no overflow sec sbc #48 ; '0' clc bcc @next @overflow sec sbc #58 ; '0' + 10 sec @next sta /3,y dey dex bne @loop bcc @end ; overflow in last digit ; calculate one more digit in next number ; store overflow in s3 inc cnt lda #'1' sta /3,y @end endm ;******************************************************************************* ; reset kernal timer defm RESET_TIMER lda #0 ; MSB ldx #0 ldx #0 ; LSB jsr KERNAL_SETTIM endm ;******************************************************************************* ; read kernal timer ; READ_TIMER variable, time is BIG ENDIAN! defm READ_TIMER sei lda time+2 sta /1 lda time+1 sta /1+1 lda time sta /1+2 cli endm ; ;******************************************************************************* *=$0801 ; 10 SYS (2064) ; BASIC start for machine language programm byte $0E, $08, $0A, $00, $9E, $20, $28, $32 byte $30, $36, $34, $29, $00, $00, $00 ;******************************************************************************* ;*=$810 main lda #147 jsr kernal_CHROUT ; clear screen PRINT_AT text1, 5, 0 PRINT_AT text2, 0, 1 PRINT_AT text3, 0, 2 PRINT_AT text4, 0, 3 ; prepare FIB(1) and FIB(2) and null other accus FILL_BLOCK 48, 1264, 80 ; accu #1 FILL_BLOCK 48, 1384, 80 ; accu #2 FILL_BLOCK 48, 1504, 80 ; accu #3 FILL_BLOCK 48, 1624, 80 ; accu #4 FILL_BLOCK 48, 1744, 80 ; accu #5 FILL_BLOCK 48, 1864, 80 ; accu #6 lda #49 ; 'print '1' sta 1823 ; accu 5 sta 1943 ; accu 6 lda #$53 sta single ; wait for key WAIT_ANY_KEY lda #2 sta cnt lda #63 sta cnt_fib RESET_TIMER main_loop CALC_FIB 1744, 1864, 1264 ; accu #1 CALC_FIB 1864, 1264, 1384 ; accu #2 CALC_FIB 1264, 1384, 1504 ; accu #3 CALC_FIB 1384, 1504, 1624 ; accu #4 CALC_FIB 1504, 1624, 1744 ; accu #5 CALC_FIB 1624, 1744, 1864 ; accu #6 WAIT_ANY_KEY dec cnt_fib beq exit jmp main_loop exit CALC_FIB 1744, 1864, 1264 ; accu #1 CALC_FIB 1864, 1264, 1384 ; accu #2 CALC_FIB 1264, 1384, 1504 ; accu #3 CALC_FIB 1384, 1504, 1624 ; accu #4 FILL_BLOCK 48, 1744, 80 ; accu #5 FILL_BLOCK 48, 1864, 80 ; accu #6 READ_TIMER duration PRINT_AT text5,0,4 jsr print_duration PRINT text6 WAIT_ANY_KEY rts ;******************************************************************************* printf ldy #0 @loop lda (ptr_out),y beq @end jsr kernal_CHROUT iny jmp @loop @end rts ;******************************************************************************* ; print duration of calculation ; 4 digit hexadecimal print_duration lda duration+1 jsr print_hex lda duration jsr print_hex rts ;******************************************************************************* ; print 8 digit hexadecimal ; A: data print_hex tax lsr A lsr A lsr A lsr A cmp #10 bcc @n1_low clc adc #7 @n1_low clc adc #"0" jsr KERNAL_CHROUT txa and #$F cmp #10 bcc @n2_low clc adc #7 @n2_low clc adc #"0" jsr KERNAL_CHROUT rts ;******************************************************************************* ; fill up to 64k data ; a: fill byte ; ptr_out: destination ; size: byte count fill_mem clc ; use carry as flag for last block sta tmp fill_mem_next lda size+1 bne fill_mem_256 sec ; last block, <256 ldx size bne fill_mem_start fill_mem_end rts fill_mem_256 ; fill 256 bytes ldx #0 fill_mem_start ldy #0 lda tmp fill_mem_loop sta (ptr_out),y iny dex bne fill_mem_loop bcs fill_mem_end dec size+1 inc ptr_out+1 jmp fill_mem_next ;******************************************************************************* ; data section ; zero page, just constants using unused BASIC memory ptr_in = $F7 ptr_out = $F9 size = $FB time = $A0 ; 3 byte kernal timer, 60Hz, big endian! ;******************************************************************************* ; real data tmp byte 0 cnt byte 0 cnt_fib byte 0 duration byte 0,0,0 single byte 0 text1 NULL "****** FIBONACCI80 *******" text2 NULL "CALCULATE FIBONACCI NUMBERS UP TO 10^80" text3 NULL "DIRECTLY IN VIDEO RAM" text4 NULL "PRESS (S)INGLE OR ANY KEY TO START" text5 NULL "TIME: $" text6 NULL " TICKS(16.66MS)"