2017-02-05 18 views
1

Я следующий ARM64 код сборки:ARM64: Как защитить весь стек при ветвлении в зависимости от сборки

.text 
.arch armv8-a 
.type testARM64, STT_FUNC 
.global testARM64 

testARM64: 
arg1 .req x0 
arg2 .req x1 
arg3 .req x2 
arg4 .req x3 
arg5 .req x4 
arg6 .req x5 
tmp .req x9 


    mov tmp, #0 

    mov x0, #1 
    bl debugAssembly 

    mov tmp, #2 

    ret 

.unreq arg1 
.unreq arg2 
.unreq arg3 
.unreq arg4 
.unreq arg5 
.unreq arg6 
.unreq tmp 

Я называю это с:

#include <stdlib.h> 

void testARM64(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6); 

void debugAssembly(int a) { 
    fprintf(stderr, "Debug 0x%d\n", a); 
} 

int main(int argc, char **argv) { 
    testARM64(0, 0, 0, 0, 0, 0); 
    return 0; 
} 

Как я могу защитить WHOLE стек при ветвлении для debugAssembly? Я имею в виду, что было бы эквивалентом команд push/pop ARM, которые могут работать WHATEVER количество аргументов и WHATEVER, которые я делаю внутри своей сборки, с ЛЮБЫМИ регистрами temp? (Мне не нужно защищать/сохранять полосы).

+0

Стандарт вызова процедуры ARM должен помочь http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf – InfinitelyManic

ответ

0

Вам необходимо сохранить реестр и регистр ссылок - часто делается с помощью чего-то типа stp x29, x30, [sp, # 0x10]! предполагая, что ваша платформа использует x29 для fp - прежде чем вы вызовете другую функцию и восстановите значения перед выходом из функции. В противном случае, когда вы будете использовать другую функцию, регистр ссылок (который содержит адрес возврата вызывающего абонента) будет перезаписан. Для вашего ABI, возможно, требуется 16-байтовое выравнивание указателя стека, поэтому вы хотите сохранить два регистра в стек, даже если ваша платформа не использует указатель кадра.

Я бы рекомендовал разобрать некоторые простые функции, сгенерированные вашим компилятором, и использовать его инструкции в качестве модели для ваших собственных ручных программ.

+0

Я использовал gcc -S для понимания того, как gcc делает это, но это всегда конкретно к текущей ситуации, ака. сколько регистров я изменил. Я хотел бы иметь возможность скопировать тот же самый отладочный код в любом месте, где он мне нужен, не беспокоясь о состоянии стека/регистров. Поэтому почему мой вопрос сказал «весь стек». – gregoiregentil

+0

Я не понимал, что вы имели в виду с «целым стеком». Вы можете сохранить все энергонезависимые (или «сохраненные пользователем») регистры в прологе функции (начало функции), а затем восстановить их в эпилогом функции (конец функции) - и это будет безопасно для всех ваших рукописных функций. AAPCS, связанный с InfinitiManic, является хорошим подтверждением того, что нужно сохранить, если ваш ABI соответствует AAPCS. Обратите внимание, что сохранение большего количества регистров, чем вам нужно сохранить, неэффективно ... и единственная причина для написания рукописной сборки - это критические функции эффективности. –