Я видел этот код на странице 120 Руководства программиста ArmV8:
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 .
ldp
/stp
отличается от A32ldrd
/strd
тем, что они могут использовать любые два целевых регистра - person Notlikethat   schedule 26.08.2015lr
, хотя возможно, что некоторые ассемблеры могут разрешить использовать его в качестве псевдонима дляx30
. Удобная ссылка на набор инструкций здесь: п - person Notlikethat   schedule 26.08.2015