ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [컴퓨터 밑바닥의 비밀] 3.3 스택 영역: 함수 호출은 어떻게 구현될까?
    Study/컴퓨터 밑바닥의 비밀 2025. 3. 9. 17:30

    스택 프레임 및 스택 영역

    • 프로세스의 스택 영역에 스택 프레임(호출 스택)이 생성
    • 프로세스의 스택 영역의 높은 주소가 맨 위에 있고 스택 영역은 낮은 주소 방향을 커짐
    • 스택 영역이 차지하는 메모리는 함수 호출 깊이에 따라 증가하고 함수 호출이 완료될수록 감소함

     

    함수 점프와 반환은 어떻게 구현될까?

    • 함수 A가 함수 B를 호출하면, 제어권이 함수 A -> 함수 B로 옮겨짐
      • 제어권: 실제로 CPU가 어떤 함수에 속하는 기계 명령어를 실행하는지
    • 제어권이 이전될 때는 다음 두 가지 정보가 필요
      • 반환(return): 어디에서 왔는지에 대한 정보 (다시 돌아갈 정보)
      • 점프(jump): 어디로 가는지에 대한 정보
    • 함수 A가 함수 B를 호출할 때 알아야 하는 정보
      • 함수 A의 기계 명령어가 어디까지 실행되었는지(어디에서 왔는지)
      • 함수 B의 첫 번째 기계 명령어가 위치한 주소(어디로 가는지)

     

    Q. 이런 정보를 어떻게 획득하고 유지할까?

    • 함수별 스택 프레임을 사용

    • 함수 B는 마지막 기계 명령어인 ret까지 계속 실행되고, 이 기계 명령어는 CPU에 함수 A의 스택 프레임에 저장된 반환 주소로 점프하도록 전달함

     

    매개변수 전달과 반환값은 어떻게 구현될까?

    • 함수를 호출할 때는 매개변수를 전달하고 반환값을 가져와야 함
    • x86-64에서는 대부분의 경우 매개변수의 전달과 반환값을 가져오는 작업을 레지스터로 함
    • CPU 내부의 레지스터 수는 제한되어 있음
    • 매개변수 수가 레지스터 수보다 많으면 나머지 매개변수는 스택 프레임에 직접 넣음
    • 새로 호출된 함수가 이전 함수의 스택 프레임에서 매개변수를 가져옴

    • 함수 B를 호출할 때 매개변수 중 일부를 함수 A의 스택 프레임에 넣음

     

    지역 변수는 어디에 있을까?

    • 지역 변수는 함수 내부에서 정의된 변수. 해당 함수에서만 사용 가능하고 외부에서는 접근 불가능
    • 로컬 변수 수가 레지스터 수보다 많으면 이 변수들도 스택 프레임에 저장

     

    레지스터의 저장과 복원

    상황

    • 레지스터는 CPU의 내부 리소스
    • CPU가 함수 A를 실행할 때 레지스터를 사용하고 CPU가 함수 B를 실행할 때도 레지스터를 사용한다면, 함수 A가 레지스터에 기록한 지역 변수 정보를 함수 B가 덮어쓸 수 있음

    방식

    • 레지스터에 새로운 지역 변수를 저장하기 전에 반드시 레지스터에 원래 저장되었던 초기값을 별도로 저장해두고, 함수 실행이 완료된 후 레지스터에 다시 그 초기값을 복원
    • 레지스터 초기값은 함수의 스택 프레임에 저장

     

    큰 그림을 그려보자, 우리는 지금 어디에 있을까?

    • 스택 영역은 프로세스 주소 공간의 일부
    • 함수가 호출될 때마다 스택 프레임은 함수 실행 시 정보를 저장하기 위해 생성되고, 함수 호출 단계가 증가함에 따라 스택 영역이 점점 더 많은 메모리를 차지함
    • 스택 영역의 크기에는 제한이 있고, 이 제한을 초과화면 stack overflow 오류가 발생함
    • 따라서 아래 사항을 주의해야 함
      • 너무 큰 지역 변수를 만들면 안된다.
      • 함수 호출 단계가 너무 많으면 안된다.
    • 참고) 유휴 영역(free segment)
      • 프로그램이 사용하는 동적 라이브러리가 이 영역에 적재됨

    댓글

Designed by Tistory.