我在ArmV8程序员指南的第120页看到了这段代码:
foo//
SUB SP, SP, #0x30
STR W0, [SP, #0x2C]
STR W1, [SP, #0x28]
STR D0, [SP, #0x20]
STR D1, [SP, #0x18]
LDR W0, [SP, #0x2C]
STR W0, [SP, #0]
LDR W0, [SP, #0x28]
STR W0, [SP, #4]
LDR W0, [SP, #0x20]
STR W0, [SP, #8]
LDR W0, [SP, #0x18]
STR W0, [SP, #10]
LDR X9, [SP, #0x0]
STR X9, [X8, #0]
LDR X9, [SP, #8]
STR X9, [X8, #8]
LDR X9, [SP, #0x10]
STR X9, [X8, #0x10]
ADD SP, SP, #0x30
RET
bar//
STP X29, X30, [SP, #0x10]!
MOV X29, SP
SUB SP, SP, #0x20
ADD X8, SP, #8
MOV W0, WZR
ORR W1, WZR, #1
FMOV D0, #1.00000000
FMOV D1, #2.00000000
BL foo:
ADRP X8, {PC}, 0x78
ADD X8, X8, #0
LDR X9, [SP, #8]
STR X9, [X8, #0]
LDR X9, [SP, #0x10]
STR X9, [X8, #8]
LDR X9, [SP, #0x18]
STR X9, [X8, #0x10]
MOV SP, X29
LDP X20, X30, [SP], #0x10
RET
我的问题是关于在例行程序结束时遵循的指示:
LDP X20, X30, [SP], #0x10
LDP用于从堆栈加载寄存器对,此指令的限制将不允许加载到该距离的寄存器。
首先,为什么这条线可以有效? 第二,为什么FP加载到x20?是不是应该加载到x29?
来自ARM程序调用标准:
每个帧应通过堆栈上两个64位值的帧记录链接到其调用者的帧
当然它也提到了这些要求不是强制性的情况,但在这种情况下FP似乎无效,因为它指向sp - 0x10,它有fp和lr。