Newer
Older
Import / research / reflection / examples / fibonacci.asm
;
; Calculate fibonacci number
;
; Ref C code:
;   https://www.programiz.com/c-programming/examples/fibonacci-series
;
.text

  _main:
        mov    %r0, #300000    ; n = 100
        mov    %r9, #10         ; r9 = 10
        mul    %r0, %r9
        mov    %r1, #1     ; i = 0
        mov    %r3, #0     ; t1 = 0
        mov    %r4, #1     ; t2 = 1
        mov    %r6, #1     ; inc = 1
    loop:
        mov    %r5, %r3    ; nextTerm = t1
        add    %r5, %r4    ; nextTerm = t1 + t2
        mov    %r3, %r4    ; t1 = t2
        mov    %r4, %r5    ; t2 = nextTerm
        add    %r1, %r6    ; i++
        cmp    %r1, %r0    ; if (i != n)
        jne    @loop
        ; print the result
        mov    %r0, %r5
        ; call   @_print_number
        ; ; exit
        ; mov    %r0, %r5
        ; ioctl  Syscall_exit
        ret          ; TODO: program exit from ret from main


  ; TODO: assembler doesn't warn when label is defined twice
  _print_number:
        mov    %r8, #0          ; r8 = 0
        mov    %r9, #10         ; r9 = 10
        mov    %r3, @zero
        mov    %r4, [%r3]       ; r4 = '0'
        mov    %r2, #10000      ; r2/place = 1000000000
        mul    %r2, %r2         ; limited to 24-bit immediates by the vm codes
        mul    %r2, %r9         ; r2 = 1,000,000,000  = required amount for doing 32-bit number printing
    find_non_leading_zero:
        mov    %r7, %r0         ; tmp = num
        div    %r7, %r2         ; tmp /= place
        div    %r2, %r9         ; place /= 10
        cmp    %r2, %r8
        je     @print_last
        cmp    %r7, %r8         ; tmp == 0
        je     @find_non_leading_zero
        mul    %r2, %r9
    printing_rest:
        mov    %r6, %r0
        mov    %r3, %r7         ; tmp2 = tmp
        add    %r3, %r4         ; tmp2 += '0'
        mov    %r0, %r3
        ioctl  Syscall_putc
        mov    %r0, %r6
        mul    %r7, %r2
        sub    %r0, %r7
        div    %r2, %r9         ; place /= 10
        cmp    %r2, %r8
        je     @done
        mov    %r7, %r0         ; tmp = num
        div    %r7, %r2         ; tmp /= place
        jmp    @printing_rest
    print_last:
        mov    %r0, %r7
        add    %r0, %r4         ; num += '0'
        ioctl  Syscall_putc
    done:
        mov    %r0, @newline
        mov    %r0, [%r0]
        ioctl  Syscall_putc
        ret

  _print_string:
        mov    %r3, #1
        mov    %r0, [%r2]
    loop3:
        ioctl  Syscall_putc
        add    %r2, %r3
        mov    %r0, [%r2]
        cmp    %r0, %r4
        jne    @loop3
        ret

.data

  zero:
        db  "0"   ; TODO: work around for not being able to assign a char literal to a register

  newline:
        db  "\n"

  str:
        db  "hello world\n"  ; comment test