简体   繁体   中英

Accessing and modifying an array in Armv8 Assembly

I am currently studying the Armv8 assembly language and don't quite understand what's happening here. We are to assume vec holds 64-bit integers and i is a 64-bit integer. We also assume that the address of vec is in x0 and that i is located in x1.

//The C equivalent: vec[i] = vec[i] * 2

lsl x1, x1, 3 // multiply i by 8 because vec of 8 byte ints
add x0, x0, x1 // add offset to base address of array
ldr x2, [x0, 0] // load item from memory
lsl x2, x2, 1 // multiply it by 2.
str x2, [x0, 0] // store it back to memory

I somewhat understand the ldr instruction as it is saying to store into the register x2 the value from x0. But I don't understand how this corresponds to the value we want in vec, and more importantly why do we need to use a logical shift left as well as the offset used in the add instruction?

A break down of this small assembly program would be very much appreciated!

An array is stored as contiguous elements in memory.

If @v is the address of the array, it will be the address of v[0]. If array items are 8 bytes, i[1] will be at @v+8, i[2] will be at @v+16, etc.

-------------------------------------------------------------------------------
|    v[0]    |    v[1]    |    v[2]    |    v[3]    |    ....    |    v[i]    |
-------------------------------------------------------------------------------
^            ^            ^            ^                         ^ 
|            |            |            |                         |            
@v           @v+8         @v+16        @v+24                     @v+i*8

We want to do v[i] = v[i] * 2

Assume

  • a copy of i is stored in reg x1
  • a copy of @v is stored in x0

What we need to do is

// 1. compute i*8 and put it in x0
lsl x1, x1, 3 // multiply i by 8 because vec of 8 byte ints
// 2. add i*8 to @v in order to compute @v[i] in x0
add x0, x0, x1 // add offset to base address of array
// 2. fetch v[i] === value at @x0 and write it to x2
ldr x2, [x0, 0] // load item from memory
// 3. multiply x2 by 2
lsl x2, x2, 1 // multiply it by 2.
// 4. write back this value at address x0
str x2, [x0, 0] // store it back to memory

Note that first instruction multiplies x1 by 8, as i 8 == i 2^3 == i<<3. First instruction could have been something like

mul x1, x1, 8 // illegal

But multiplication by an immediate does not exist in arm asm and it would require two instructions.

mov x4, 8
mul x1, x1, x4

Shift instruction is equivalent (and cheaper).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM