I won’t list long theories here. Instead, I will show how a real compiler does. I will take GCC as an instance here.
- Branch Code
============================
(1) near call
test1.c
arm-none-eabi-gcc -fomit-frame-pointer -c test1.c -S -o test1.s
(2) long call
void sub_80077E8(s16 *mempool);
void call_sub_80077E8(s16 *mempool)
{
sub_80077E8(mempool);
}

hint:
thumb → arm: bx pc
arm → thumb: bx 90008b5h
#pragma long_calls
void sub_8007824(s16 *mempool);
#pragma long_calls_off
void call_sub_8007824(s16 *mempool)
{
sub_8007824(mempool);
}
(3) call thumb from arm
(copied from Nintendo’s official SDK)
Hint: why mov lr,pc here?

test2A.s

test2callA.s
arm-none-eabi-gcc -fomit-frame-pointer -s test2A.s test2callA.s
arm-none-eabi-objdump -S a.out

WRONG!
Hint: why?
change test2A.s

RIGHT:

(4) call arm from thumb
test2A.s

test2callA.s
the result:


(5) function pointer
test3.c
arm-none-eabi-gcc -fomit-frame-pointer -mthumb -c test3.c -S
(6) callback
test4.c
arm-none-eabi-gcc -fomit-frame-pointer -mthumb -c test4.c -S
- Arguments, Return Value and Local Variables
===================
(1) at most 4 parameters
test5.c
arm-none-eabi-gcc -fomit-frame-pointer -mthumb -c test5.c -S
Hint:
a1: r0->[sp,#4]->r3->r0=>r0->[sp,#4]
a2: r1->[sp]->r2->r1=>r1->[sp]


















































