в зависимости от настроек компилятора и от того, какое ядро предназначается, bx без lr очень распространено, если не требуется, поскольку pop старых ядер (обычно ldmia) lr не работает для переключения между режимами arm и thumb, поэтому компиляторы будутсгенерируйте pop как r3, а затем bx r3.
extern unsigned int more_fun ( void );
unsigned int fun ( void )
{
return(more_fun()+1);
}
00000000 <fun>:
0: b510 push {r4, lr}
2: f7ff fffe bl 0 <more_fun>
6: 3001 adds r0, #1
8: bc10 pop {r4}
a: bc02 pop {r1}
c: 4708 bx r1
e: 46c0 nop ; (mov r8, r8)
vs
00000000 <fun>:
0: b508 push {r3, lr}
2: f7ff fffe bl 0 <more_fun>
6: 3001 adds r0, #1
8: bd08 pop {r3, pc}
a: bf00 nop
r4 против r3, поскольку фиктивный регистр здесь не имеет значения, интересно, что это делает компилятор, но они просто используются для выравнивания стека,не сохранять регистр.
это, конечно, режим большого пальца, режим охраны
00000000 <fun>:
0: e92d4010 push {r4, lr}
4: ebfffffe bl 0 <more_fun>
8: e8bd4010 pop {r4, lr}
c: e2800001 add r0, r0, #1
10: e12fff1e bx lr
, вы ожидаете увидеть, что lr используется с bx lr
или это дляновее, но gcc, по крайней мере, по умолчанию работает в режиме большого пальца, и вы должны заставить его генерировать код руки, подобный следующемувозможный.если это встроенная система, и все находится в энергонезависимой памяти (flash / rom / etc), то в какой-то момент, если код находится в оперативной памяти, он копируется или распаковывается или иным образом в оперативную память перед переходом на ветвь.С другой стороны, вы, возможно, разбирали некоторый код, который может вызывать код в ram, но этот код в ram может поступать из загрузки, в основном это какой-то внешний источник, который в конечном итоге отсутствует на плате / чипе.Подобно загрузчику, в котором есть код для загрузки программы через uart и последующего перехода к ней, это не означает, что код используется нормально, и, безусловно, означает, что вы не можете предсказать или знать, каким будет этот код, тем более найти его и разобрать.
bx из not lr можно использовать вручную для запуска в такой код, если я загружаю в 0x20000000 и каким-то образом знаю, что это код большого пальца, а не рука, тогда мне нужно каким-то образом направить адрес с 1, затем bxк тому же, иногда вы делаете это с помощью регистра, иногда нет.
вы также увидите bx, используемый компоновщиком для исправления чего-то далеко или для изменения режимов:
unsigned int more_fun ( void )
{
return(3);
}
компоновщик добавляет батут для вас:
00000000 <fun>:
0: e92d4010 push {r4, lr}
4: eb000003 bl 18 <__more_fun_from_arm>
8: e8bd4010 pop {r4, lr}
c: e2800001 add r0, r0, #1
10: e12fff1e bx lr
00000014 <more_fun>:
14: 2003 movs r0, #3
16: 4770 bx lr
00000018 <__more_fun_from_arm>:
18: e59fc000 ldr r12, [pc] ; 20 <__more_fun_from_arm+0x8>
1c: e12fff1c bx r12
20: 00000015 andeq r0, r0, r5, lsl r0
24: 00000000 andeq r0, r0, r0
и в этом случае используется r12.