Мы пытаемся объяснить, что вам нужно сделать это, если вы хотите использовать r4 в функции:
.globl asm_test
asm_test:
stmdb r13!,{r4}
mov r0, #4 @make sure r0 is not the same as r4
mov r4, #1 @move to r4 something different from r0
ldmia r13!,{r4}
mov pc, lr @return from function
В противном случае вы оставляете бомбу замедленного действия, которая взорвется в какой-то момент в будущем. Компилятор выделил r4 для чего-то в функции более высокого уровня, и по правилам никто не может изменить этот регистр так, чтобы вызов более высокого уровня не должен был защищать r4, путая его в нужное время и в месте, где вы создаете проблему, как проблема ведет себя в зависимости от кода. И объясню, почему другие регистры в этом случае не чувствительны. Иногда, когда вы делаете это, вы на самом деле не вылетаете, иногда, возможно, строка печатается неправильно или цикл повторяется или выходит рано.
Чтобы увидеть, что происходит, пожалуйста, разберите соответствующую функцию (не исходный код, а разборка). плюс функции, которые его вызывали, и функции, которые вызывали его до тех пор, пока в одной из этих окружающих функций не появится r4 проверьте, для чего используется r4.
Вы также можете изменить поведение, если бы ваша вызывающая функция asm_test () имела локальные переменные, которые используются до и после вызова asm_test () таким образом, что оптимизатор хранит их в регистрах, но также так, чтобы оптимизатор не удаляет код все вместе:
void fun ( void )
{
int r;
r=10;
asm_test();
r++;
}
Оптимизатор полностью удалит r в приведенном выше коде, но:
int fun ( int a, int b, int c, int d )
{
int e;
e=a+b+c+d;
b=asm_test(a+d);
e+=b;
return(e);
}
создает более чем достаточно, чтобы заставить компилятор создать кадр стека.
00000000 <fun>:
0: e0811000 add r1, r1, r0
4: e92d4010 push {r4, lr}
8: e0830000 add r0, r3, r0
c: e0814002 add r4, r1, r2
10: e0844003 add r4, r4, r3
14: ebfffffe bl 0 <asm_test>
18: e0840000 add r0, r4, r0
1c: e8bd8010 pop {r4, pc}
r4 - это переменная e в этом случае (вокруг вызова asm_test), и, запутав r4, вы измените то, что возвращает функция fun (). Если это значение никогда не использовалось, например, для вызова fun, ваша модификация r4 осталась бы незамеченной.
Компиляторы следуют правилам соглашения о вызовах и ожидают, что все вызываемые абоненты также будут это делать, если вы возразите, что пути, которые могут привести к сбою / сбою, перерастут от безрезультатного к довольно серьезному, поэтому вы должны соответствовать этим соглашениям о вызовах в вашем ASM.