需要帮助找出ARM中的分段错误

问题描述

所以我最近收到了一个第二年计算机科学模块的项目,我们在那里进行计算机体系结构设计。我们被要求编写ARM汇编代码,以输出n = 15和n = 30的斐波那契数列。

我已经尝试过在线检查多种资源,但是ARM的使用不那么广泛,在2020年也不再受支持。我已经能够编译并运行我的代码,但是它告诉我“分段错误”并输出错误的数字(139)。

在过去的一个周末,我一直处于困境,尝试进行多次修复,但没有运气。如果有人可以指导我正确的方向,或者帮助我确定我的逻辑或语法错误,那就太好了。我将在下面发布代码,并在此先非常感谢您!

.global  main
.func main
main:
        LDR R5,=0x50000000    ; load mem address
        MOV R1,#5             ; number comparisons

.loop:
        LDR R2,[R5]         ; load 1st number
        ADD R6,R5,#04      ; increment address to next number
        LDR R3,[R6]        ; load 2nd number
        ADD R4,R2,R3

        STR R4,[R6,#4]     ;store in next mem location
        MOV R5,R6

        SUBS R1,#01        ; decrement counter
        BNE .loop           ; loop mechanism
        nop
.endfunc
BX LR

解决方法

您的代码崩溃是因为您尝试读取/写入随机地址。根据公式128 +信号编号(SIGSEGV是信号11),外壳程序会将崩溃转换为退出状态139。

通常,您不应该简单地选择一些随机地址并将数据存储在那里。这几乎总是崩溃,如果没有崩溃,那么该地址的内存仍然有可能被程序中的其他内容占用。

要解决此问题,应显式分配一些内存,并使用该内存区域的地址。最简单的方法是使用静态内存分配并将所需的数据放入.data部分:

        .section .data    ; enter .data section
data:   .int 0            ; first number
        .int 1            ; second number

在这里,data是一个符号。您可以给它指定任意名称,但其名称在源文件中必须唯一。然后,您可以在程序中加载data的地址,而不用硬编码0x50000000

        ldr r5,=data     ; load the address of data

请注意,如果要在定义变量后将代码放置在文件中,则需要切换回.text部分。代码(即程序文本)始终进入.text部分。

        .section .text    ; switch back to the .text section

在文件的开头,当前部分隐式为.text部分,但是通常最好在发出任何类型的代码或数据之前始终显式切换这些部分。

还可以将未初始化的数据放在.bss部分中。如果您要分配数据数组并且不想键入那么多.int指令,则此功能特别有用。

        .section .bss     ; enter .bss section
data:   .space 8          ; reserve 8 bytes of memory

.data部分相反,不可能在.bss部分中指定内存的初始值。初始值始终是一系列零。