无论堆栈向上还是向下增长,完全取决于您所查看的系统的ABI。也就是说,我所涉及的所有arm64代码都是向下增长的堆栈。
因此,一个常见的推送操作看起来像这样:
stp x29, x30, [sp, -0x10]!
而且还有一首像这样的流行歌曲:
ldp x29, x30, [sp], 0x10
这显然是一次同时推/弹出两个寄存器,因此每次修改堆栈指针16字节,这就引出了下一部分:
堆栈对齐检查。堆栈指针是否必须对齐到16字节边界也取决于你所使用的ABI,但这是一个实际的硬件特性,可以进行配置。
参见
ARMv8参考手册,
SCTLR_EL[123]
包含了打开或关闭每个异常级别的这个特性的位。例如,引用自
SCTLR_EL1
的内容如下:
SA0, 位 [4]
EL0级别的SP对齐检查使能。当设置为1时,如果在EL0级别执行的加载或存储指令使用SP作为基地址,并且SP未对齐到16字节边界,则会引发SP对齐错误异常。更多信息请参见
第D1-2333页的SP对齐检查。
当实现了ARMv8.1-VHE,并且HCR_EL2.{E2H, TGE}的值为{1, 1}时,该位对EL0级别的执行没有影响。
在一个PE重置为EL1的系统中,该字段将重置为一个架构上未知的值。
SA, 位 [3]
SP对齐检查使能。当设置为1时,如果在EL1级别执行的加载或存储指令使用SP作为基地址,并且SP未对齐到16字节边界,则会引发SP对齐错误异常。更多信息请参见
第D1-2333页的SP对齐检查。
当实现了ARMv8.1-VHE,并且HCR_EL2.{E2H, TGE}的值为{1, 1}时,该位对PE没有影响。
在一个PE重置为EL1的系统中,该字段将重置为一个架构上未知的值。