레지스터와 호출 규약
인자는 r0~r3, 반환값은 r0, 돌아갈 주소는 lr, 스택 위치는 sp. 함수 경계에서 레지스터가 어떻게 쓰이는지 정한 약속.
Cortex-M 레지스터
| 레지스터 | 역할 |
|---|---|
| r0~r3 | 인자 전달, 반환값(r0), 함수 안에서 자유롭게 씀 |
| r4~r11 | 함수가 쓰려면 저장했다가 복원해야 함 |
| r12 | 임시 |
| r13 (sp) | 스택 포인터 |
| r14 (lr) | 돌아갈 주소 |
| r15 (pc) | 프로그램 카운터 |
| xPSR | 플래그와 예외 번호 |
AAPCS 호출 규약
- 인자 4개까지는 r0~r3, 다섯 번째부터는 스택으로
- 64비트 값은 r0:r1처럼 두 레지스터를 씀
- 호출된 함수는 r4~r11을 쓰면 시작할 때 push, 끝날 때 pop
그래서 인자를 4개 이하로 유지하면 스택 접근이 줄어 빨라집니다. 인자가 많으면 구조체 포인터 하나로 넘기는 것이 낫습니다.
인터럽트와의 관계
Cortex-M은 예외에 들어갈 때 r0~r3, r12, lr, pc, xPSR을 하드웨어가 자동으로 저장합니다. 호출 규약상 "호출된 쪽이 보존할 필요 없는" 레지스터를 미리 저장해 두기 때문에, 인터럽트 처리 함수를 평범한 C 함수로 쓸 수 있습니다.