【问题标题】:ARMv7 assembly store values in an arrayARMv7 程序集将值存储在数组中
【发布时间】:2015-03-16 20:59:58
【问题描述】:

我正在尝试将用户输入的数字添加到数组中的每个元素。在我意识到原始数组没有被更新之前,我一切正常。很简单,我想,只需将值存储回数组中并继续生活。可悲的是,这似乎并不那么简单。

正如标题所示,我正在使用 ARMv7 并编写程序集。我一直在使用this guide 来了解基础知识并查看一些好的代码。当我运行此处给出的示例代码时,它工作正常:str r2, [r3]r2 中的任何内容放入r3 指向的内容中。以下是我尝试做同样的事情,这给了我Signal 11 occurred: SIGSEGV (Invalid memory segment access)Execution stopped at: 0x0000580C STR r3,[r5,#0]

@ Loop and add value to all values in array regardless of array length
@ Setup loop
@ r4 comes from above and the scanf value, I've checked the registers and the value is correct
mov     r0, #0
ldr     r1, =array_b
ldr     r2, addrArr
loop:                   @ Start loop to add inputed number to every value in array
    add     r3, r2, r0
    ldr     r3, [r3]
    add     r3, r3, r4  @ Add input to each index in array

    add     r5, r2, r0  @ Pointer to location in array
    str     r3, [r5]    @ Put new value into array

    cmp     r0, r1      @ Check for end of array
    addne   r0, r0, #4  @ Not super necessary but it shows one of the cool things ARM can do, condition math
    bne     loop        @ Branch if not equal
    beq     doneLoop    @ Branch if equal

doneLoop:               @ End loop

这里是变量

.align  2
array:
    .word   0
    .word   1
    .word   2
    .word   3
    .word   4
    .word   5
    .word   6
    .word   7
.equ    array_b, .-array
addrArr:    .word array

我的理解是str 首先获取源,然后获取目标(由于某种原因,这与其他指令不同)。所以r5 用于计算数组中存储值的位置,r3 具有来自add 指令的值。我检查了r5 中的值是有效的,即:它是数组的开头,array_b 是正确的长度(在这种情况下为 32)。我也尝试过使用=array 而不是addrArr,但它们给出了相同的值和相同的段错误消息。

【问题讨论】:

  • 另外,您的代码非常臃肿。我知道这不是你的问题,但我不能不指出来。不需要每次都添加数组的基址和索引,只需执行一次。使用正确的寻址模式,你甚至不需要做一次,它是由处理器自动完成的。您的循环应该适合 4 条指令。最后,最后一条beq 指令什么都不做。
  • 我对此很陌生,我很想知道更好的方法来做到这一点!您能否提供一个快速示例或链接到某处讨论此问题的地方?
  • 是的,this page 似乎是关于 ARM 可以为寻址模式做些什么的相当好的参考

标签: arrays assembly armv7


【解决方案1】:

这是因为历史上系统中有两种主要的记忆:

  • ROM,只读存储器,不能写入,只能存储程序和常量数据
  • RAM,随机存取存储器,可以读写。它用于存储变量。

许多系统不直接使用 ROM,而是可以从其他永久支持(例如软盘、磁带或硬盘)将数据加载到 RAM 中。为了避免程序写入不应该写入的 RAM 内存,可以使用 分段内存将 RAM 划分为多个区域。

并非所有系统都具有此功能,因此它实际上取决于架构。如果使用分段内存,当您尝试写入设计为只读的 RAM 段时,它基本上会使处理器退出应用程序。这正是您的问题所在。

为了解决这个问题,你应该声明你的数组,它是一个变量,应该存储在 RAM 中,在它前面加上 .data

另一方面,你的可执行指令应该放在用汇编指令.text标记的只读段中

【讨论】:

  • gcc 将代码放入.rodata?为什么我要使用.text 而不是.rodata
  • 段在链接器脚本中描述,它的作用是告诉链接器哪些段在地址空间中的哪个位置。我怀疑 gcc 将 .rodata.text 分开以分离代码和常量数据,但我不确定所以我在这里可能是错的。如果分段页面支持此功能,这可以防止您错误地将常量数据作为代码执行。 Here is 似乎是链接描述文件使用的一个很好的参考。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多