【问题标题】:pass by reference in assembly在汇编中通过引用传递
【发布时间】:2013-03-10 15:47:24
【问题描述】:

我正在尝试编写一个程序来使用 ARM-C 互通计算数字的指数。我正在使用 LPC1769(cortex m3) 进行调试。以下是代码:

/*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);
}

这是补充上述 C 代码的汇编代码

.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

但是在调试会话期间,我遇到了执行“Exponentiatecore(m,n)”的 Hardfault 错误。

如调试窗口所示。

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>

我是在对齐过程中造成了一些堆栈损坏,还是我的解释有误? 请帮忙。 提前谢谢你

【问题讨论】:

  • 我不知道你的错误是什么,但对你已经尝试过的事情 +1。
  • @rekire 是讽刺还是欣赏?
  • 赞赏:恕我直言,新用户以如此好的方式完成其家庭作业并不常见。
  • 根据this forum post,您可以在硬故障异常处理程序中使用此获取发生异常的PC:MRS R0,PSP/LDR R1,[R0,#24]。一旦您知道是哪条指令导致了硬故障,就应该更容易找出原因。
  • @Michael 感谢您的建议。硬故障是由于从 1. 第一次从汇编切换到 C 时压入链接寄存器的值引起的 bl Exponentiate (lr=0x27B) 2. 第二次从 C 切换到汇编 --- result=Exponentiatecore(米,n); (lr=0xfffffff9) 我知道我正在破坏返回值,但是如何在第一个开关中保存 lr 值??

标签: pointers assembly stack pass-by-reference lpc


【解决方案1】:

您的代码存在几个问题。首先是你有一个无限循环,因为你的 SUB 指令没有设置标志。将其更改为 SUBS。下一个问题是您不必要地操作 LR 寄存器。你不会从 Exponentiatecore 调用其他函数,所以不要碰 LR。函数的最后一条指令应该是“BX LR”返回给调用者。问题 #3 是您的乘法指令是错误的。除了取 3 个参数外,如果将数字乘以自身,它会增长得太快。例如:

ExponentiateCore(10, 4);
通过每个循环的值:
R4 = 10,n = 4
R4 = 100,n = 3
R4 = 10000,n = 2
R4 = 100,000,000 n = 1

问题 #4 是您正在更改非易失性寄存器 (R4)。除非您保存/恢复它们,否则您只能丢弃 R0-R3。试试这个:

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

【讨论】:

  • "您的 SUB 指令没有设置标志"。自从我上次阅读 ARM 文档以来已经有一段时间了,但由于这是 Thumb 代码,我很确定算术操作总是表现得好像它们有一个 S 后缀。
  • 我通常不使用 Thumb,所以这是有道理的。 Cortex M3 支持看起来更像 ARM 指令的 Thumb-2。最初的崩溃可能是由于更改了 R4 和 R9 而没有保留它们。
  • 只是我正在做的事情的一个小代表....#1 C--> 程序集(开始例程)--->#2 C 函数(指数)---> #3 程序集(Exponentiatecore())....我仍然无法纠正堆栈损坏错误。提前致谢
  • 非常感谢BitBank。我已经根据您的建议实施了更改。它部分工作#1 但我从 main.c 文件调用 Start 以便切换到程序集,因此我保存 lr 值.. #2 带有指向 Exponentiate 的链接的分支(int * ,int *) 函数来自程序集,因此又多了一个开关。#3 现在再次从 C 分支到 Exponentiatecore(m,n) 到程序集。执行第 3 步后,仍然出现硬故障。根据迈克尔的建议,我发现错误指令是这一行 result=Exponentiatecore(m,n); ..在执行这一行之后,堆栈指针被破坏了。
  • @BitBank start() 例程就在程序集文件的顶部。从开始调用 C Exponentiate() 函数。当省略第三个分支(exponentiatecore)时,程序可以正常工作的另一件事。在这种情况下,没有硬故障。 “result= Exponentiatecore(m,n)”是问题所在。 :( :(
【解决方案2】:

我只是添加 开始: 推 {r4-r11,lr} ... 弹出 {r4-r11,pc}

指数核:@ r0-&m, r1-&n 推 {r4-r11,lr} ... 弹出 {r4-r11,pc}

并在“开始”中清理 bl 打印,一切正常

【讨论】:

    猜你喜欢
    • 2015-02-24
    • 1970-01-01
    • 1970-01-01
    • 2013-11-05
    • 2011-01-14
    • 2015-01-15
    • 2019-07-03
    • 2011-01-31
    • 1970-01-01
    相关资源
    最近更新 更多