0

I am currently enrolled in an assembly language (Motorola 68K Assembler) course. I have a project where I am tasked with printing the result of a Fibonacci number of a number up to 30. For example, if the user were to enter 4, the result should be 3 (since it is the sum of the previous two numbers). However, my main program (prog4.s) continuously prints out 0. Does the problem have anything to do with the logic of the recursive method? Does the problem lie elsewhere? Here is my code of the recursive method (fib.s)

* fib.s
* long fib(int n) {
*     if(n==0) { 
*      return 0;
*     }
*     else if(n==1) {
*      return 1;
*     }
*     return fib(n-1) + fib(n-2);
* }

ORG $7000

fib:
    link      A6,#0
    movem.l   D1-D2,-(SP)
    move.w    8(A6),D1
    TST.w     D1
    BNE       next
    BRA       out

next:
    cmpi.w    #1,D1
    BNE       recurse
    add.w     #1,D0
    BRA       out

recurse:
    move.w    D1,D2
    subq.w    #1,D1
    move.w    D1,-(SP)
    JSR       fib
    move.w    D0,D1      * save copy of fib(n-1)

    adda.l    #2,SP

    subq.w    #2,D2
    move.w    D2,-(SP)
    JSR       fib
    add.w     D2,D1
    add.w     D1,D0        * return fib(n-1) + fib(n-2)

    adda.l    #2,SP

out:
    movem.l   (SP)+,D1-D2
    unlk      A6
    rts

    end

Here is my code for the program that calls fib.s

fib:   EQU   $7000
start: initIO
setEVT

lineout     title
lineout     prompt
linein      buffer
cvta2       buffer,D1

* Place parameter on the stack and move the stack pointer
move.w      D1,-(SP)

*Jump to the fib subroutine
JSR         fib

*Pop starting parameter off the stack 
adda.l      #2,SP

cvt2a       buffer,#6
stripp      buffer,#6
lea         buffer,A0
adda.l      D0,A0
clr.b       (A0)
lineout     answer

break

prompt:     dc.b 'Enter a number between 1 and 30: ',0
answer:     dc.b 'The Fibonacci number is: '
buffer:     ds.b  80
       end

Something to note: The algorithm commented out in fib.s is the one I am required to use. Any help/advice would be much appreciated.

  • 1
    Did you try single-stepping your code in a debugger? I assume your 68k simulator has a debugger built-in, because it's an essential tool for asm development. – Peter Cordes Dec 07 '16 at 21:15
  • Minor code optimization, instead of checking for `n == 0` or `n == 1` it could be `if (n < 2) return n;` – Frank C. Dec 07 '16 at 23:01
  • @FrankC, I agree with you on that optimization. However, the algorithm commented out in fib.s is the one I am required to use for this project. –  Dec 07 '16 at 23:14

2 Answers2

4

Your program is almost correct.
The problem is not within the logic of the recursion it self, it's how you return the values computed by each invocation.
A couple of tracing sessions with the debugger will help you spot the problem.

I'm giving you a hint first. These lines

add.w     D1,D2      *fib(n-1) + fib(n-2)
add.w     D2,D0      *add fib(n-2)

don't do what the comments say.
D2 holds n-2, D1 holds fib(n-1) and D0 is fib(n-2) so the end result is fib(n-1) + fib(n-2) + n - 2. Just replace them with ADD.W D1, D0 to return fib(n-1) + fib(n-2).

There are two other mistakes, yet in how you return the value for the other two cases (n = 0 and n = 1).

I strongly suggest you to try using the 68k simulator that comes with Easy68k to debug a call to fib(0) and fib(1) by yourself.
An important advice: set D0 to a random value (say: $55555555) before starting the simulation and use F7 to trace the execution.

If you fail at finding the other mistakes, here they are

The instruction used to return 1 for the n = 1 case is ADD.W #1, D0 which depends on the previous value of D0.
It should be MOVE.W #1, D0.
If n = 0 the function branches to out without modifying D0, it should set D0 to zero.
Something like MOVE.W #0, D0 or another zeroing idiom.

zx485
  • 28,498
  • 28
  • 50
  • 59
Margaret Bloom
  • 41,768
  • 5
  • 78
  • 124
  • Hi @Margaret Bloom, I was able to successfully add your corrections to my code. The corrections should be visible in my original post now since I edited it. However, my program is still printing out zero. I added the code that calls the subroutine to the original post as well. Do you think there could be a problem with accessing the returned value (which should be placed in D0)? –  Dec 08 '16 at 15:21
  • 1
    @ChristopherMoussa Your program run verbatim from the updated question performs correctly. I've tested it with SIM68K using `move.w #11, -(SP)` / `jsr fib` and it (correctly) returns 89 in `D0`. I don't know what `linein` and `cvta2` are, you may want to check that they are used correctly. Finally, questions have a historical value. You should rollback the changes to show what your original problem was. – Margaret Bloom Dec 09 '16 at 14:09
  • I was also able to run this successfully on my simulator. I discovered that the problem lied within my register use (which is explained in my answer). Thank you for your help! –  Dec 09 '16 at 15:59
0

The problem lies within the calling program, prog4.s. You read in the value correctly, but you were passing the wrong register onto the stack. The macro linein stores the two's complement integer in D0, not D1. Since D1 had zeros in it before you passed it in, it was returning zero every time. This is what the correct code of the calling program should be:

fib:    EQU             $7000
start:  initIO                  * Initialize (required for I/O)
        setEVT                  * Error handling routines
*       initF                   * For floating point macros only


lineout         title
lineout         prompt
linein          buffer
cvta2           buffer,D0


* Place parameters on the stack and move the stack pointer
move.w          D0,-(SP)


* Jump to the fib subroutine
JSR             fib


* Pop starting parameters off of the stack
adda.l          #2,SP


cvt2a           buffer,#6
stripp          buffer,#6
lea             buffer,A0
adda.l          D0,A0           * Sets A0 to the address of D0
clr.b           (A0)
lineout         answer


break                           * Terminate execution
*
*----------------------------------------------------------------------
*       Storage declarations


title:  dc.b    'Program #4, Christopher Moussa, cssc0702',0
prompt: dc.b    'Enter a number between 1 and 30: ',0
answer: dc.b    'The Fibonacci number is: '
buffer: ds.b    80
    end