ARM에서는 R14를 LR(Link-Register)라는 특수한 용도로 사용을 한다. 이 LR은 Branch Instruction으로 분기를 할때 Return Address를 담고 있다가 Return을 할때 사용한다. 하지만 더 이상 다른 함수를 호출하지않는 Leaf 함수라면 LR 값을 계속 가지고 있어도 상관 없지만, 다른 함수를 호출하는 함수라면 LR은 어떻게 해야 할까? 당연히 스텍에 Push를 한다.

아래와 같은 코드를 컴파일해서 보자

void NO_RET_NO_ARG_NO_LEAF();
void NO_RET_NO_ARG_LEAF();

void NO_RET_NO_ARG_NO_LEAF() {
  NO_RET_NO_ARG_LEAF();
  return;
}

void NO_RET_NO_ARG_LEAF() {
  return;
}

간단한 코드다. NO_RET_NO_ARG_NO_LEAF()에서 NO_RET_NO_ARG_LEAF()을 호출한다. NO_RET_NO_ARG_LEAF()은 이름처럼 Leaf Function이라 아무것도 호출하지 않는다.

$ arm-none-eabi-gcc -g3 -O0 -c leaf_no_leaf.c

컴파일을 할 때는 -g3으로 디버그 info를 최대한 많이 생성해주고, -O0으로 방금 작성한 아무짝에도 쓸모없는 코드가 진짜 아무짝에도 쓸모없는 취급을 받아 버려지지 안도록 해준다. 아무짝에도 쓸모 없지만 예제로써 쓸모있으니까.

$ arm-none-eabi-objdump -t leaf_no_leaf.o 

leaf_no_leaf.o:     file format elf32-littlearm

SYMBOL TABLE:
...
00000000 g     F .text  0000001c NO_RET_NO_ARG_NO_LEAF
0000001c g     F .text  00000018 NO_RET_NO_ARG_LEAF

먼저 생성된 Symbol 정보를 파악하고, Start Address와 Size를 기반으로 Disassemble(-d)을 해주자. C 소스와 같이 보면 이해하기 편하니까 -S 옵션도 같이.

$ arm-none-eabi-objdump -M reg-names-apcs -dS --start-address 0x00000000 --stop-address $((0x00000000 + 0x0000001c + 0x00000018)) leaf_no_leaf.o

leaf_no_leaf.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <NO_RET_NO_ARG_NO_LEAF>:
void NO_RET_NO_ARG_NO_LEAF();
void NO_RET_NO_ARG_LEAF();

void NO_RET_NO_ARG_NO_LEAF() {
   0:   e92d4800        push    {fp, lr}
   4:   e28db004        add     fp, sp, #4
  NO_RET_NO_ARG_LEAF();
   8:   ebfffffe        bl      1c <NO_RET_NO_ARG_LEAF>
  return;
   c:   e1a00000        nop                     ; (mov r0, r0)
}
  10:   e24bd004        sub     sp, fp, #4
  14:   e8bd4800        pop     {fp, lr}
  18:   e12fff1e        bx      lr

0000001c <NO_RET_NO_ARG_LEAF>:

void NO_RET_NO_ARG_LEAF() {
  1c:   e52db004        push    {fp}            ; (str fp, [sp, #-4]!)
  20:   e28db000        add     fp, sp, #0
  return;
  24:   e1a00000        nop                     ; (mov r0, r0)
}
  28:   e28bd000        add     sp, fp, #0
  2c:   e49db004        pop     {fp}            ; (ldr fp, [sp], #4)
  30:   e12fff1e        bx      lr

0:에서는 LR의 값이 다음 함수 호출때 세로운 값으로 뭉개지기 때문에 FP와 같이 LR을 Stack에 Push해준다. 하지만 1c:를 보면 FP만 Push를 해준다.

AAPCS: