pass by reference in assembly

非 Y 不嫁゛ 提交于 2019-12-10 15:28:50

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!