스택프레임

혼연보다가 스택프레임이란 부분을 읽고  까먹지말아야지 하면서 서치해서 글좀 퍼왔음!!

스택프레임: 함수가 호출될 떄 스택에는 함수로 전달되는 인수, 실행을 마치고 돌아올 복귀 번지, 지역변수 등의 정보들이 
저장된다. 스택에 저장되는 함수의 호출 정보를 스택 프레임이라고한다.



 

컴퓨터 메모리는 코드스택힙 영역으로 나누어 지는 것을 알고 계실 겁니다여기서 우리가 보고자 하는 부분이 스택 영역
이며
,
이는 함수를 호출하게 될 시 이용되지요.

 

다음 소스를 보도록 하죠.

 

void function() {}

 

void main() {

       

           function();

 

}

 

매우 간단하게 짜 보았습니다. main() 함수에서 function 함수를 호출하지요하는 일은 아무것도 없습니다
하지만메모리 상에서는 main 함수로부터 어딘가에 존재하는 function 함수를 찾아가야 하고 function 함수가 종료되면
function 함수가 호출되었던 위치인 main 함수로 돌아올 수 있어야 합니다.

 

당연히 main 함수 입장에서는 function 함수의 위치를 알 수 있겠죠. function 함수의 위치는 컴파일 당시에 지정이 되니깐요 

하지만, function 함수 입장에서는 자신이 돌아갈 위치를 알 수 없습니다.

 

따라서 main함수에서 function 함수를 호출하기 직전에 반드시 현재 위치를 스택 영역에 저장을 해야 합니다그리곤 
function 
함수가 
끝나면 스택 영역에 저장된 main함수로의 복귀 주소를 참고하여 다시 돌아오죠.

 

사실 그림이 없어도 위 내용은 어느 정도 이해가 될 거라고 생각합니다.

 

그럼 다음 소스를 보도록 하죠.

 

void Function1() {

           int b = 3;          //2

           Function2();     //3

}

 

void Function2() {

           int c = 4;          //4

}         

void main() {

           Function1();     //1

}

 

하는 일은 설명 안해도 쉽게 이해할 수 있는 정도입니다그럼 주석으로 번호를 매긴 시점의 스택 상황을 그림으로 보도록 합시다.

 

 

        

 

     

 

 

 

        

 

 


참고로 ESP는 포인터 레지스터 중 하나이며 32비트 Stack Pointer를 나타냅니다재 스택 영역에서 가리키고 있는 위치를 기억하고 있지요. 따라서 스택 공간에 데이터가 하나씩 추가될 때마다, ESP 역시 4바이트씩 증가하게 됩니다그리곤 스택에서 다시 데이터를 가져오면서 스택에 존재하는 데이터는 제거할 필요없이 ESP 위치를 4바이트씩 감소만 시키면 됩니다.

 

 

위 사진은 Function1, Function2를 거친 후다시금 main함수로 돌아왔을 당시의 스택 영역의 모습입니다기록된 데이터는 여전히 남아있지만 ESP의 위치는 다시 MAIN의 복귀 주소로 돌아왔지요.

 

여기까지 해서우리는 동에번쩍 서에번쩍 함수에서 함수로 이동이 가능한 이유를 내부적으로 살펴보았습니다.

 

그럼 함수에서 반환값은 어떻게 전달될까요이는, EAX 범용 레지스터에 기록하여 반환값을 가져옵니다. 64비트 반환값 같은 경우는 EAX EDX를 사용하죠.

 

그럼질문 하나 더함수 호출 시 인자로 전달되는 데이터는 어떻게 되나?

 

 void function1( int a, int b ) {

           int c = 5;

}

 

void main() {

           function1( 3, 2 );

}

 

 

 

사실 컴파일 시 생성된 어셈블리 언어를 보면 다음과 같은 부분이 있습니다.

 

 function1:

     push ebp

     mov ebp, esp

  

스택 프레임의 원리에 있어서 함수 진입 시에 스택 포인터를 ebp( 32비트 Base Pointer )에 따로 저장하는 것이죠. 그 이유는 무엇일까요?

 

ebp는 디버깅 시 유용히 사용하기 위한 것이죠.

 

 void function( char* p ) { 

           p = A;                 

}

 

void main() { 

           function( 0 );           

}

  

위 소스를 보면 p = A’ 시점에서 에러가 발생하겠죠에러가 발생하는 시점의 스택의 구조입니다.

 

마치 연결 리스트와 같은 방식으로 EBP를 추적해 나가면 함수 호출 시점들을 추적해 나갈 수 있으며 최초 EBP + 0X04 를 통해 최초  MAIN 함수로까지 돌아갈 수 있지요.

 

 

 

이상 스택 프레임에 대해서 간략히 소개해 보았습니다. 이해가 안되시면 정덕영 저서의 윈도우즈 구조와 원리 (한빛 미디어) 책을 추천합니다.  

 

 

- 참고 : 윈도우즈 구조와 원리(한빛미디어) -
- 출저 : 
http://hermet.pe.kr/56227646 



 

혼연에도 아주 자세히 나와있다.

함수 고급->호출규악->스택프레임

이 글을 공유하기

댓글

Designed by JB FACTORY