Вы говорите, что цель перехода "принимает аргумент указателя на 64-разрядное целое число и возвращает 64-разрядное целое число", но это не так.Он принимает указатель на 64-разрядное целое число в качестве единственного аргумента (и этот указатель имеет длину 32 бита, если вы не используете aarch64, что я сомневаюсь, учитывая оставшуюся часть кода);и он ничего не возвращает, он просто перезаписывает 64-битное значение, на которое указывает аргумент, который вы передали. Я уверен, что это то, что вы имели в виду, но будьте осторожны при использовании терминологии, потому что разница между этими вещами важна!В частности, ни одна из 64-битных аргументов не передается в нашу функцию, которую вы вызываете.
В отношении самого вопроса.Ключ к пониманию того, что делает компилятор, заключается в том, чтобы взглянуть на самую первую строку:
push {r0, r1, r4, r5, r6, lr}
Соглашение о вызовах ARM *1007* не требует r0
и r1
длябыть сохраненным по вызову, так что они делают в списке?Ответ в том, что компилятор добавил эти «фиктивные» нажатия, чтобы создать место в стеке.Операция push
, указанная выше, по существу эквивалентна
push {r4, r5, r6, lr}
sub sp, sp, #0x08
, за исключением того, что она сохраняет инструкцию.Конечно, результат не совсем тот же, потому что все, что было в r0
и r1
, в итоге записывается в эти места;но, учитывая, что нет никакого способа узнать, что там было заранее, и собранные значения в любом случае будут перезаписаны, это не имеет значения.Таким образом, мы имеем в качестве фрейма стека
lr
r6
r5
r4
(r1)
sp -> (r0)
с указателем стека, указывающим на пространство, создаваемое фиктивным толчком r0
и r1
.Теперь у нас просто есть
mov r0, sp
, который копирует указатель стека в r0
для использования в качестве аргумента-указателя для функции, которую вы вызываете, которая затем перезапишет два слова в этом месте, что приведет ккадр стека
lr
r6
r5
r4
(64-bit value, high word)
sp -> (64-bit value, low word)
Вы не показали никакого кода, кроме blx r3
, поэтому невозможно точно сказать, что происходит со стеком в конце функции.Но если эта функция не возвращает аргументов, я ожидаю увидеть совпадение
pop {r0, r1, r4, r5, r6, pc}
, что, конечно, приведет к тому, что ваш 64-битный результат останется в r0
и r1
.Но эти регистры закрыты в соответствии с соглашением о вызовах, поэтому проблем нет.