问题
I am trying to write a program to calculate the exponential of a number using ARM-C inter-working. I am using LPC1769(cortex m3) for debuuging. The following is the code:
/*here is the main.c file*/
#include<stdio.h>
#include<stdlib.h>
extern int Start (void);
extern int Exponentiatecore(int *m,int *n);
void print(int i);
int Exponentiate(int *m,int *n);
int main()
{
Start();
return 0;
}
int Exponentiate(int *m,int *n)
{
if (*n==0)
return 1;
else
{
int result;
result=Exponentiatecore(m,n);
return (result);
}
}
void print(int i)
{
printf("value=%d\n",i);
}
this is the assembly code which complements the above C code
.syntax unified
.cpu cortex-m3
.thumb
.align
.global Start
.global Exponentiatecore
.thumb
.thumb_func
Start:
mov r10,lr
ldr r0,=label1
ldr r1,=label2
bl Exponentiate
bl print
mov lr,r10
mov pc,lr
Exponentiatecore: // r0-&m, r1-&n
mov r9,lr
ldr r4,[r0]
ldr r2,[r1]
loop:
mul r4,r4
sub r2,#1
bne loop
mov r0,r4
mov lr,r9
mov pc,lr
label1:
.word 0x02
label2:
.word 0x03
however during the debug session, I encounter a Hardfault error for the execution of "Exponentiatecore(m,n)".
as seen in debug window.
Name : HardFault_Handler
Details:{void (void)} 0x21c <HardFault_Handler>
Default:{void (void)} 0x21c <HardFault_Handler>
Decimal:<error reading variable>
Hex:<error reading variable>
Binary:<error reading variable>
Octal:<error reading variable>
Am I making some stack corruption during alignment or is there a mistake in my interpretation? please kindly help. thankyou in advance
回答1:
There are several problems with your code. The first is that you have an infinite loop because your SUB instruction is not setting the flags. Change it to SUBS. The next problem is that you're manipulating the LR register unnecessarily. You don't call other functions from Exponentiatecore, so don't touch LR. The last instruction of the function should be "BX LR" to return to the caller. Problem #3 is that your multiply instruction is wrong. Besides taking 3 parameters, if you multiplied the number by itself, it would grow too quickly. For example:
ExponentiateCore(10, 4);
Values through each loop:
R4 = 10, n = 4
R4 = 100, n = 3
R4 = 10000, n = 2
R4 = 100,000,000 n = 1
Problem #4 is that you're changing a non-volatile register (R4). Unless you save/restore them, you're only allowed to trash R0-R3. Try this instead:
Start:
stmfd sp!,{lr}
ldr r0,=label1
ldr r1,=label2
bl Exponentiatecore // no need to call C again
bl print
ldmfd sp!,{pc}
Exponentiatecore: // r0-&m, r1-&n
ldr r0,[r0]
mov r2,r0
ldr r1,[r1]
cmp r1,#0 // special case for exponent value of 0
moveq r0,#1
moveq pc,lr // early exit
loop:
mul r0,r0,r2 // multiply the original value by itself n times
subs r1,r1,#1
bne loop
bx lr
回答2:
I just add Start: push {r4-r11,lr} ... pop {r4-r11,pc}
Exponentiatecore: @ r0-&m, r1-&n push {r4-r11,lr} ... pop {r4-r11,pc}
and clean bl print in Start and all work fine
来源:https://stackoverflow.com/questions/15542360/pass-by-reference-in-assembly