1. 문제의 배경: CPU 레지스터는 모든 함수가 공유하는 단 1세트의 공간입니다
CPU 안에 존재하는 연산용 레지스터는 함수마다 따로 주어지는 것이 아닙니다.
컴퓨터에 존재하는 단 1개의 레지스터 세트를 함수 P도 쓰고, 함수 P가 호출한 다른 함수 Q도 똑같이 사용합니다.
따라서 함수 P가 레지스터에 중요한 값을 넣어두었는데, 함수 Q를 호출하면 Q가 자기 계산을 하느라 그 레지스터의 값을 덮어써서 지워버리는 문제가 발생합니다.
2. ABI 규약이 정한 2가지 레지스터 보존 규칙
- Caller-saved 레지스터 (호출한 쪽이 알아서 챙기기):
%rax, %rdi, %rsi, %rdx, %rcx, %r8 ~ %r11
- 호출받은 함수 Q는 이 레지스터들을 마음대로 덮어써도 됩니다.
- 따라서 P는 Q를 호출한 뒤에도 이 레지스터 값을 써야 한다면, Q를 호출하기 전에 스택 메모리에 자기가 직접 저장해 두어야 합니다.
- Callee-saved 레지스터 (호출받은 쪽이 원상복구해 주기):
%rbx, %rbp, %r12, %r13, %r14, %r15 (총 6개)
- 호출받은 함수 Q는 이 레지스터의 원래 값을 손상시키면 안 됩니다.
- Q가 이 레지스터를 사용하려면 함수 시작 시 스택 메모리에
pushq로 백업해 두고, 함수가 끝나서 복귀하기 직전에 popq로 원래 값으로 복구해 주어야 합니다.
3. CS:APP 연습문제 3.34: 지역 변수가 스택에 저장되는 계산 과정
함수 P가 지역 변수 7개(a1 ~ a7)와 입력 변수 x를 다루는 코드:
- 사용할 수 있는 Callee-saved 레지스터는 총 6개입니다.
- 그중
%rbx 레지스터는 입력 인자 변수 x를 보존하는 데 먼저 할당되었습니다.
- 남은 Callee-saved 레지스터는 5개뿐입니다.
- 지역 변수 7개 중 5개(
a1 ~ a5)는 남은 5개의 레지스터에 할당됩니다.
- 자리(레지스터)가 부족해서 남은 2개의 변수(
a6, a7)는 RAM 메모리인 스택 프레임 공간((%rsp), 8(%rsp))에 저장됩니다.
4. 결론 요약
- CPU 레지스터 개수는 한정되어 있습니다.
- 보존해야 할 변수 개수가 레지스터 개수보다 많아지면, 넘쳐나는 변수들은 스택 메모리에 저장합니다.