armv8 里面似乎没有了 v7 中的块访存指令,就是一次性访问一块内存的指令。我们还是先介绍下 v7 中的块访存指令。
V7中的块访存指令

手册中介绍了很多种该指令的变种形式,其实了解了这个指令的英文含义就都很好理解。
LD - load,加载
M - Memory,内存
IA,IB,DA,DB,这四个表示的是模式。
FA,FD,EA,ED,这四个是针对特殊寄存器的特殊写法。
举个例子:
该指令表示的意思是,从 R0 表示的地址处开始读内存,一次性读4个64bit的数出来,放到 R1 到 R4 中。储存的顺序,就是序号顺序。我们看其格式描述:

寄存器列表一共占据了 16 位,可以描述 16 个寄存器,每一个位为1就表示需给该寄存器赋值。
1E 就是第1位到第4位是1。符合 R1 - R4 的描述。
下面,我们重点介绍一下指令后缀,IA,IB,DA,DB。
IA,IB,DA,DB
知道了英文含义,应该就能理解其含义了,与
i++ 和++i差不多。
看指针行为,先读 R0 寄存器内存地址处的数据,读完再下移,直到 4 个数据都读完。最后R0的值是不变的。如果需要改变 R0 的值,需要加上 ! 后缀。

看指针行为,先下移,再读 R0 寄存器内存地址处的数据,直到 4 个数据都读完。最后R0的值是不变的。如果需要改变 R0 的值,需要加上 ! 后缀。

DA 与 DB 就是反着来的,就不重复了。
IB 与 DB 的行为和栈操作会比较像,push与 pop。
FA,FD,EA,ED
FD:满递减堆栈。
FA:满递增堆栈。
EA:空递减堆栈。
ED:空递增堆栈。
我们尝试在 ida 中 patch 一个指令:
发现,ida 给我们生成的指令是:
实际上,是因为该指令的第一个操作数是 SP,所以才会生成 FD 后缀。所以,STMFD 与 STMDB 是一样的。
比如,我们经常会在函数的头尾看到如下指令:
第一条指令就是,保存 R3-R7 的值,保存返回地址,最后一条指令,就是还原 R3-R7 的值,将返回地址赋值给 PC。
V8中的块访存指令
虽然,V8中没有了V7中的那些指令,但是还有一个平替指令,就是 STP 指令,我们在函数头尾有时候也能见到。
看下 STP 指令的介绍:

stp 指令是 str 的变种指令,p 可以理解成 pair 的意思,可以同时操作两个寄存器。从V7中的最多操作16个,变成了2个,威力下降了不少。
举一个例子:
看一下,mencpy 的汇编:
对 STP 的指令使用还是比较疯狂的。
看一下 STP 的储存方向:


按下 F7,查看 sp 变化:

可以看到,在低地址
0000007FF2D3AF00位置先储存了X1,然后在高地址0000007FF2D3AF08储存了 X2。这里的两个数据在栈中储存的感觉有点别扭,或许我应该理解成先将 sp + 16,然后先储存 x2,再储存x1,毕竟栈生长方向是向低地址的。









