Question

This program is a simple modification to my previous problem of pass by reference in assembly. This calculates the exponential i.e 2^2 Here is the program--

#include<stdio.h>
#include<stdlib.h>
extern int Start_func (void);
extern int Exponentiatecore(int m,int n);
void print(int i);
int Exponentiate(int m,int n);

int main()
{
printf("in main func\n");
Start_func();
return 0;
}


int Exponentiate(int m,int n)
{
printf("in exponentiate func\n");

    if(n==0)
     return 1;
    else
    {
        int result=0;
        result=Exponentiatecore(m,n);    
        printf("calculation done\n");
        printf("result=%d\n",result);
        return (result);
    }

}


void print(int i)
{
printf("value=%d\n",i);
}

Here is the assembly code which complements it--

Start_func:
    mov r5,lr
            mov r0,#2
    mov r1,#2
    bl Exponentiate
    bl print
    mov lr,r5
    bx lr

Exponentiatecore:    // r0->m, r1->n

           mov r2,r0
       loop:
           mul r2,r0
           subs r1,#1
           bne loop
           mov r0,r2
           bx lr

This is the disassembly---

      Start_func:
00000270:   mov r5, lr
00000272:   mov.w r0, #2
00000276:   mov.w r1, #2
0000027a:   bl 0x2bc <Exponentiate>   //branch to exponentiate function
0000027e:   bl 0x31c <print>
00000282:   mov lr, r5
00000284:   bx lr 
      Exponentiatecore:
00000286:   mov r2, r0
      loop:
00000288:   mul.w r2, r0, r2
0000028c:   subs r1, #1
0000028e:   bne.n 0x288 <loop>
00000290:   mov r0, r2
00000292:   bx lr 


      main:
0000029c:   push {r7, lr}
0000029e:   add r7, sp, #0
000002a0:   movw r3, #11300 ; 0x2c24
000002a4:   movt r3, #0
000002a8:   mov r0, r3
000002aa:   bl 0xdbc <printf>
000002ae:   bl 0x270 <Start_func>
000002b2:   mov.w r3, #0
000002b6:   mov r0, r3
000002b8:   pop {r7, pc}
000002ba:   nop 
      Exponentiate:
000002bc:   push {r7, lr}
000002be:   sub sp, #16 
000002c0:   add r7, sp, #0
000002c2:   str r0, [r7, #4]
000002c4:   str r1, [r7, #0]
000002c6:   movw r3, #11316 ; 0x2c34
000002ca:   movt r3, #0 
000002ce:   mov r0, r3
000002d0:   bl 0xdbc <printf>
000002d4:   ldr r3, [r7, #0]
000002d6:   cmp r3, #0
000002d8:   bne.n 0x2e0 <Exponentiate+36>
000002da:   mov.w r3, #1
000002de:   b.n 0x312 <Exponentiate+86>
000002e0:   mov.w r3, #0
000002e4:   str r3, [r7, #12]
000002e6:   ldr r0, [r7, #4]
000002e8:   ldr r1, [r7, #0]
000002ea:   blx 0x284 <Start_func+20>      //this jump should be at 0x286
000002ee:   mov r3, r0
000002f0:   str r3, [r7, #12]
000002f2:   movw r3, #11340 ; 0x2c4c
000002f6:   movt r3, #0
000002fa:   mov r0, r3

I get an hard fault error during debugging on the instruction-->

result=Exponentiatecore(m,n);

I am using LPC 1769(Embedded Artists) on NXP LPC Xpresso IDE by code_red.

If you take a look at this line--> 000002ea: blx 0x284

it should jump to 0x286 where the Exponentiatecore() function starts, but unfortunately the jump is one instruction above that.

Can anyone please tell where I am going wrong in the above code. Thank you in advance.

Was it helpful?

Solution

This is a clue:

000002ea:   blx 0x284 <Start_func+20> 

The blx instruction tries to switch into ARM mode, which does not work on a Cortex M3.

You need to declare your assembly functions as thumb:

# ---------------------------------------------
# mode of asembly
# ---------------------------------------------
      .syntax unified
      .thumb
      .arch armv7m

# ---------------------------------------------
# allocation
# ---------------------------------------------
.text
.global Start_func
.thumb_func
Start_func:
    mov r5,lr
    [...]
.thumb_func
Exponentiatecore: 

Otherwise the linker thinks they are arm functions and tries to switch to that mode - which results in a fault.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top