Ответ 1
1.) Как я понял, что некоторые дополнительные gcc-флаги необходимы для толкания дополнительно pc и sp в функции proog? Если да, то каковы они?
Существует много опций gcc, которые влияют на фреймы стека (-march
, -mtune
и т.д. могут влиять на инструкции, используемые для примера). В вашем случае это было -mapcs-frame
. Кроме того, -fomit-frame-pointer
удалит кадры из функций листа. Несколько статических функций могут быть объединены вместе в одну сгенерированную функцию, что дополнительно уменьшает количество кадров. APCS может вызвать несколько более медленный код, но необходим для трассировки стека.
2.) Для чего это используется? В принципе, поскольку я понимаю, что могу разматывать стек только с FP и LR, зачем мне эти дополнительные значения?
Все регистры, которые не являются параметрами (r0-r3), должны быть сохранены, поскольку они должны быть восстановлены при возврате вызывающему абоненту. Компилятор будет выделять дополнительные локали в стеке, поэтому sp
будет почти всегда изменяться при изменении fp
. Почему хранится pc
, см. Ниже.
3.) Если это ничего не болит с флагами компиляции - как я могу заставить генерацию этой расширенной функции пролога и снова в чем цель?
Это флагов компилятора, как вы уже догадались.
; Prologue - setup
mov ip, sp ; get a copy of sp.
stm sp!, {fp, ip, lr, pc} ; Save the frame on the stack. See Addendum
sub fp, ip, #4 ; Set the new frame pointer.
...
; Epilogue - return
ldm sp, {fp, sp, lr} ; restore stack, frame pointer and old link.
... ; maybe more stuff here.
bx lr ; return.
Типичное сохранение stm sp!, {fp, ip, lr, pc}
и восстановление ldm sp, {fp, sp, lr}
. Это правильно, если вы изучите документы ABI/APCS. Обратите внимание, что нет! попытаться исправить стек. Он загружается явно из сохраненного значения ip
.
Кроме того, сохраненный pc
не используется в эпилоге. Это просто отброшенные данные в стеке. Так зачем это делать? Обработчики исключений (прерывания, сигналы или исключения С++) и другие механизмы трассировки стека хотят знать, кто сохранил фрейм. ARM всегда имеет только один пролог функции (одна точка входа). Однако есть несколько выходов. В некоторых случаях возврат, подобный return function();
, может фактически превратиться в b function
в, возможно, больше материала. Это называется хвостом. Также, когда функция листьев вызывается в середине процедуры и возникает исключение, она увидит диапазон листа pc
, но на листе не может быть кадра вызова. Сохраняя pc
, кадр вызова может быть проверен, когда в листке появляется исключение, чтобы узнать, кто действительно сохранил стек. Таблицы pc
по сравнению с деструктором и т.д., Возможно, хранятся, чтобы позволить освободить объекты или выяснить, как вызвать обработчик сигнала. Дополнительный pc
просто приятен при трассировке стека, и операция почти свободна из-за подкладки труб.
Смотрите также: ARM Link and frame register вопрос о том, как компилятор использует эти регистры.