dlkulp
dlkulp

Reputation: 2274

ARMv7 assembly store values in an array

I'm trying to add a user inputted number to a every element in an array. I had everything working until I realized that the original array was not being updated. Simple, I thought, just store the value back into the array and move on with life. Sadly, this doesn't seem to be quite so simple.

As the title suggests, I'm using ARMv7 and writing assembly. I've been using this guide to understand the basics and to have some good code to look at. When I run the example code given here it works fine: str r2, [r3] puts whatever is in r2 into what r3 points at. The following is my attempt to do the same thing which gives me a Signal 11 occurred: SIGSEGV (Invalid memory segment access) and 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

Here are the vars

.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

My understanding is that str takes the source first and the destination second (which is different from other instructions for some reason). So r5 is used to calculate where in the array to store the value and r3 has the value from the add instruction. I've checked and the value in r5 is valid, ie: it's the start of the array and the array_b is the proper length (32 in this case). I've also tried doing =array instead of addrArr but they give the same value and the same segfault message.

Upvotes: 2

Views: 4145

Answers (1)

Bregalad
Bregalad

Reputation: 634

This is because there is historically in systems two major kind of memories :

  • ROM, Read Only Memory, cannot be written to and can store only the program and constant data
  • RAM, Random Access Memory, can be both read and written to. It is used to store variables.

Many systems do no use ROM directly, instead the data can be loaded from an other permanent support, for example a floppy disc, a tape or a hard disc into RAM. In order to avoid a program writing to RAM memory that wasn't supposed to be written, the RAM can be divided in multiple areas, using segmented memory.

Not all system features this, so it really depends on the architecture. If segmented memory is used, it basically makes the processor quit the application when you try to write to a segment of RAM that is designed to be read only. This is exactly what appears to be your problem here.

In order to solve this you should declare your array, which is a variable and should be stocked in RAM, by precedding it by .data.

On the other hand your executable instructions should be placed in the read only segment marked with the assembler directive .text

Upvotes: 1

Related Questions