ARM Assembly 中的偏移量是从开始还是结束算起?

Does offset in ARM Assembly counts from the start or the end?

我是 ARM 汇编的新手,我想了解当您使用 STUR 存储时实际机器代码的样子。举个例子,这里是 64 位

0000 0000 0000 0000 0000
0000 0000 0000 0000 0000
0000 0000 0000 0000 0000
0000 

现在当我打电话时

STUR X0, [X29,#var_8] ; Store the value of X0 (0xB) into the stack at offset 0x8

变成了吗

0000 0000 1011 0000 0000
0000 0000 0000 0000 0000
0000 0000 0000 0000 0000
0000 

0000 0000 0000 0000 0000
0000 0000 0000 0000 0000
0000 0000 0000 1011 0000
0000

内存是字节可寻址的。因此,描述内存的最佳方式是标记地址并显示字节值。通常这是用十六进制完成的,但我想二进制也可以。

 Address  Value
10010000   00
10010001   44
10010002   33
10010003   55
...

有时一行显示多个字节,只有一个地址号:

 Address  Value
10010000   00 44 33 55
10010004   ...
...

地址对于理解内存的工作原理很重要。



0000 0000 1011 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

十六进制并按字节分组为 00 B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00

这个值,在小字节序中解释为 64 位数字是 45056(十进制)。


0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1011 0000 0000

十六进制并按字节分组为 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0B 00

上面的值,在小字节序中解释为 64 位数字是 2816(十进制)。


所以,你的问题的答案都不是,存储的值将是

B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

因为这是 little endian 中值为 0xB 的字节序列,也就是 x0.

中的 0x000000000000000B

需要说明的是,ARM 处理器也可以 运行 作为大端,但这似乎并不常见。


偏移量非常重要,因为它会更改写入 x0 中的值的地址。

将偏移量添加到基址寄存器(此处为 x29)以形成所谓的有效地址,它决定了第一个字节将被写入的地址。内存中的多字节项目由字节中的最低地址引用——正是这个地址与内存系统通信(连同指示内存传输大小和方向的控制信号,此处为 16 bytes/64-bits 并写入内存)。

写入内存的值仍然是16字节,所以16个不同的连续地址的内存字节被更新。字节将根据小端字节顺序以内存顺序出现。

可以使用 16 byte/64 位读取从内存中读取该值,这将在 CPU 寄存器中获得值 0x00..000B。该内存位置的读取不必在偏移量中匹配,只有有效地址需要是相同的位置才能引用相同的项目,并且将生成相同有效地址的任何寻址模式都可以读取该值

例如,如果堆栈指针从将更多的东西压入堆栈而移动——压入时堆栈指针向下移动到更小的值,以容纳额外的项目(已经在堆栈上的东西留在它们所在的位置)地址条款)——然后当使用堆栈指针作为基址时,偏移量需要增加以引用与在将其他项目推入堆栈之前写入的相同有效地址;增加的数量需要与推送的项目大小完全匹配,以保持有效地址相同。