Skip to main content
PPopo
Associate III
May 31, 2021
Solved

ARM assembly - Fibonacci Implementation: PUSH and POP not working as expected

  • May 31, 2021
  • 3 replies
  • 3778 views

 have written this ARM assembly code. It is supposed to put the Fibonacci sequence numbers in R4 register. I'm trying to implement this C code in assembly:

int fibbonacci(int n) 
 
{ 
 
 if(n == 0)
 
 return 0; 
 
 else if(n == 1) 
 
 return 1; 
 
 else 
 
 return (fibbonacci(n-1) + fibbonacci(n-2));
 
}

This is the assembly code I have written:

 AREA |.text|, CODE, READONLY 
 
 EXPORT Fib 
 
Fib 
 
 ;R0(n) - store the first n numbers in the Fibonacci sequence 
 
 ;R1 - address of the first element in the array to store the Fibonacci sequence 
 
 MOV R4, #0 
 
 MOV R5, #0 
 
 MOV R6, #1 
 
 
 
FiboR 
 
 CMP R0, #1 
 
 PUSHEQ {R5, R6, LR} 
 
 BEQ Return 
 
 SUBS R0, R0, #1 
 
 BL FiboR 
 
 ADD R4, R2, R3 
 
 PUSH {R4, R2, LR} 
 
Return 
 
 POP {R2, R3, PC} 
 
 ALIGN END

It is not behaving exactly like that posted C code so far because I need to keep working on it and make it return to main after it prints the first 5 numbers. However for now I need to fix something.

When my code reaches this line:

PUSH {R4, R2, LR}

It's supposed to push values R4, R2 and LR on the stack which at that moment are: 1, 0, LR.

Then the code goes down into the 'Return' subroutine in which I'm doing this:

POP {R2, R3, PC}

So at this moment R2 should be loaded with value 1, R3 with value 0 and PC with value of LR so I return to this line:

ADD R4, R2, R3

The code does return to the ADD line however the value of R2 is not loaded with the value 1 as I expected it to. My code stays here in an infinite loop and I keep pushing {1, 0, LR} on the stack but when I try to pop these values into R2, R3 and PC apparently they are not getting popped as I would expect them to at least value 1 does not go into R2 and R2 keeps it's value of 0 forever.

Can you please help me what am I missing here? Thank you for reading!

    This topic has been closed for replies.
    Best answer by waclawek.jan

    The processor does not work as you'd think, but it works according to its specification:

    0693W00000BZgCSQA1.pngAs it's PUSH where you don't have the registers in ascending order, you should've seen the "incorrect" (or unexpected) order of values on the stack.

    Yes, the assembler might've warned. Maybe it did but maybe not; assemblers these days are mostly intended as backend to compilers, which are supposed to generate sane code. What toolchain are you using?

    JW

    3 replies

    waclawek.jan
    waclawek.janBest answer
    Super User
    May 31, 2021

    The processor does not work as you'd think, but it works according to its specification:

    0693W00000BZgCSQA1.pngAs it's PUSH where you don't have the registers in ascending order, you should've seen the "incorrect" (or unexpected) order of values on the stack.

    Yes, the assembler might've warned. Maybe it did but maybe not; assemblers these days are mostly intended as backend to compilers, which are supposed to generate sane code. What toolchain are you using?

    JW

    PPopo
    PPopoAuthor
    Associate III
    May 31, 2021

    Hello. Thank you for your answer!

    I'm using Keil5. I guess that is the toolchain? :D

    And after reading your answer I have switched the orders of the registers when pushing them and now it works :D. Thank you! I was not aware they are pushed in ascending order I thought they are pushed and popped as I write them.

    The snapshot you posted is from the ARMv7-M Architecture Reference Manual, correct?

    waclawek.jan
    Super User
    May 31, 2021

    > The snapshot you posted is from the ARMv7-M Architecture Reference Manual, correct?

    Yes.

    > I'm using Keil5.

    It appears that this https://www.keil.com/support/man/docs/armasm/armasm_dom1359731150961.htm describes how do you enable a warning when the registers are not written in the "usual" ascending order.

    JW