解析ARM64汇编指令内存寻址方式

内存操作指令​

ARM所有的运算指令只能基于寄存器,所以,要先从内存Load要运算的数据到寄存器,运算完成后,再将寄存器的结果Store到内存,这两个操作相应的指令如下:

解析ARM64汇编指令内存寻址方式_第1张图片

 还有Mov指令,但是并不能从内存读写数据,只能是直接的一个数(立即数),或者寄存器:

解析ARM64汇编指令内存寻址方式_第2张图片

指令不难理解,麻烦的是[addr],各种姿势,婉转百变,今天抽时间解锁一下

寻址方式

首先[addr]里面一定有一个寄存器,这个寄存器的值是一个内存地址,称之为Base Register,可以理解为c语言里面的一个ptr。Base Register在寻址之前或者之后都可以进行一些运算操作,操作结果可以更新到这个Base Register,也可以不更新到Base Register。具体来说,有下面几种:

  • 最简形式:Base Register模式

    可类比于:*(ptr) <-> value

    下面的x1不会变

ldr  x0,  [x1]   /* [x1] -> x0 */
  • 带感叹号!的形式:Pre-Index寻址模式

    可类比于:*(++ptr) <-> value

    下面的x1会先更新,然后用来寻址

    典型的:入栈操作,先栈指针sp--,然后数据入栈

str x2, [x1, x2, LSL#2]!  /* x2->[x1 + x2<<2];x1 = x1 + x2 << 2 */
  • 单纯的[REG]的形式:Post-Index寻址模式

    可类比于:*(ptr++) <-> value

    下面的x1在寻址完成后,再更新

    典型的:出栈操作,先数据出栈,然后sp++

ldr x3, [x1], x2, LSL#2  /* x3 <- [x1]; x1 = x1 + x2 << 2 */ 
  • 其它的形式:Offset寻址模式

    可类比于:*(ptr + xxx) <->value

    下面的x1不会更新

str x2, [x1, x2, LSL#2]  /* x2 -> [x1 + x2 << 2] */

更多的例子

  • Pre-Index模式

ldr   x3, [x1, #4]!
ldr   x3, [x1, r2]!
ldr   x3, [x1, r2, LSL#2]!
stp   x0, x1, [sp, #-16]!  /* 入栈:sp = sp - 16;x1/x0->sp */
  • Post-index模式

ldr   x3, [x1], #4
ldr   x3, [x1], r2
ldr   x3, [x1], r2, LSL#2
ldp   x29, x30, [sp], #0x10   /* 出栈:x30/x29
  • Offset模式

ldr   x3, [x1, #4]
ldr   x3, [x1, r2]
ldr   x3, [x1, r2, LSL#2]

立即数

说一下立即数,形式可以为:

  • #

  • =

mov w2, #14 << 4
bic x4, x4, #((1 << 21) - 1)

#的方式对位数和运算操作有限制,如果编译出错,可以换成如下的形式

ldr  =

=只能用于ldr指令

temp_var: .word 0
ldr x1, =temp_var
ldr x1, =0x0000000000802520

解析ARM64汇编指令内存寻址方式_第3张图片

ARM官方说明:参考链接

解析ARM64汇编指令内存寻址方式_第4张图片

解析ARM64汇编指令内存寻址方式_第5张图片

你可能感兴趣的:(解析ARM64汇编指令内存寻址方式)