<aside> 💡 스택은 어떻게 생겼을까? 스택 프레임과 스택 allocation 등등 여러 이론적으로 들은건 있지만, 실제로 본 적은 없다.
</aside>
이 글은 arm64의 레지스터와 instruction set에 대해서는 따로 설명하지 않는다. 조만간 이에 대해 정리하는 글을 하나 써 보도록 하겠다.
필자는 macOS Ventura 13.4.1에서 실험하였으며, Apple clang 14.0.3로 플래그 없이 컴파일하였다. 디버거는 lldb를 사용하였고, disassembly는 otool -tv 명령어로 하였다.
우선 간단한 코드 하나를 준비해 보았다.
int main(void) {
return 0;
}
효과적으로 아무것도 하지 않는 C 코드이다.
_main:
0000000100003fb0 mov w0, #0x0
0000000100003fb4 ret
w0 레지스터에 리턴값인 0x0을 넣고, 바로 리턴한다.
arm64 c abi를 확인해 보면 w0/x0 레지스터가 정수 리턴값을 들고 있는다. 즉 return 0;가 mov w0, #0x0과 같다는 의미이다.
ret 는 기본적으로 x30 lr (link register)레지스터에 있는 주소로 돌아가게 한다. x30 레지스터에는 무엇이 있을까? lldb로 확인해 보자.

바로 dyld 프로세스이다. dynamic linker로, 우리의 프로그램을 실행시켜준 OS 코드이다.
int main(void) {
int i = 0;
return 0;
}
_main:
0000000100003fa4 sub sp, sp, #0x10
0000000100003fa8 mov w0, #0x0
0000000100003fac str wzr, [sp, #0xc]
0000000100003fb0 add sp, sp, #0x10
0000000100003fb4 ret
sp 는 stack pointer 레지스터이다. 첫 줄을 보면 sp를 0x10만큼 감소시키는걸 볼 수 있다. 바로 이 행동이 스택을 allocate하는 것이다. 0x10, 즉 16바이트의 스택을 allocate했다.
두 번째 줄은 w0 레지스터에 0x0 값을 넣었다. 위에서 본 리턴 값 준비이다.