在Armv8 Assembly中访问和修改阵列

时间:2019-02-21 02:32:19

标签: assembly armv8

我目前正在研究Armv8汇编语言,并且不太了解这里发生了什么。我们假设vec拥有64位整数,而i是64位整数。我们还假定vec的地址在x0中,而我在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

我有点理解ldr指令,因为它说的是将x0中的值存储到寄存器x2中。但是我不明白这与我们在vec中想要的值如何对应,更重要的是为什么我们需要使用逻辑左移以及add指令中使用的偏移量?

非常感谢您打破这个小汇编程序!

1 个答案:

答案 0 :(得分:0)

数组作为连续元素存储在内存中。

如果@v是数组的地址,它将是v [0]的地址。如果数组项是8位,则i [1]将位于@ v + 8,i [2]将位于@ v + 16,等等。

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

我们想做v [i] = v [i] * 2

假设

  • i的副本存储在reg x1
  • @v的副本存储在x0中

我们需要做的是

// 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

请注意,第一指令将x1乘以8,因为i * 8 == i * 2 ^ 3 == i << 3。最初的指示可能是

mul x1, x1, 8 // illegal

但是在arm asm中不存在立即数乘法,因此需要两条指令。

mov x4, 8
mul x1, x1, x4

Shift指令是等效的(并且更便宜)。