시스템 프로그래밍 노트 5 - 함수와 스택 메모리

2019년 10월 22일

어떻게 함수가 호출되고 인자가 전달될 것인지에 대해 살펴본다. - x64 Calling Convention

1. 스택

기본적으로 서브루틴은 스택을 통해 관리된다. 스택은

대충 형태는 다음과 같다:

%rbp -> 0x7fffffffdd08
        0x7fffffffdd00
        0x7fffffffdcf8

        ...

%rsp -> 0x7fffffffdc08

%rsp가 내려갈수록 서브루틴 하나가 점유하는 메모리 공간이 늘어난다. 그래서 스택은 아래로 자란다라는 표현이 쓰이기도 한다.

%rbp가 선택적이라는 뜻은 x64 Calling Convention에서는 %rbp를 굳이 사용 안해도 서브루틴을 무사히 만들 수 있기 때문이다. 만약에 사용되었다면 가장 높은 스택 프레임 주소이다. 어떻게 사용될 수 있는지는 1.2 참조.

1.1. 관련된 인스트럭션

크게 네 가지가 있다.

push와 pop은 정반대의 인스트럭션이다. 그래서 어떤 레지스터를 메모리에 저장했다가 나중에 다시 불러오고 싶을 때 다음과 같이 사용하기도 한다.

1.2. 인자 전달

x64에서 인자는 레지스터를 통해 직접 전달된다.

보통 %rbp를 사용하는 경우 함수는 다음과 같은 형태이다. 예전 %rbp를 저장한 후 %rbp를 그 함수의 스택 메모리를 할당하기 전의 %rsp 값으로 설정한다. 이를 통해 이 함수의 가장 높은 스택 프레임 주소가 %rbp로 무사히 설정된다.

push %rbp
mov %rsp, %rbp
...
pop %rbp

1.3. Saving Conventions

같은 레지스터를 다른 프레임의 함수에서 사용하면 충돌한다. 이를 방지하기 위해서 레지스터 별로 saving cocnvention 이 존재한다.

이런 Callee Saved 레지스터를 저장하고 리턴 전에 불러오는 패턴을 push, pop으로 해결할 수 있다.

push %rbx
...
pop %rbx