반응형
  설명                                                                             스택 프레임                   SP 위치

1. 스택은 현재 초기값(sp) 상태

   이 상태에서 함수호출(CALL nnnn)이 들어오면

 

 ←SP(한칸위를 가리켜야되는데 그림이..)

들어온곳을 가리킴

 

 

 


2. 함수의 인자(두개라고 가정한다.)와 다음 명령어 주소를 차례로 PUSH 한다. 이때 인자의 푸시 순서는는 오른쪽에서 왼쪽으로(FIFO 이므로) 하며 다음 명령어 주소(이것이 복귀 주소이다.)는 IP 에 들어있다.

   그리고 IP를 호출 함수의 시작주소로 변경한다

argument 1

←SP

argument 2

IP(복귀 주소)

 

 

 

 

 


3. IP가 피호출함수의 시작주소로 변경되었으므로 함수가 시작된다. 함수에 진입하면 일단 BP레지스터를 스택에 PUSH한다.(이전 BP를 유지하지 위함. 아래에서 BP 레지스터를 SP를 저장하는 용도로 사용하기 때문에 함수를 여러번 호출할 경우를 대비해 BP를 스택에 넣어두는 것이 필요하다.)

argument 1

←SP

argument 2

IP(복귀 주소)

BP

 

 

 

 


4. 그 뒤 SP를 BP에 옮긴다.(BP=SP). 이것은 함수내에서의 SP 사용으로 SP가 계속 내려가기 때문에 BP를 SP의 저장용도로 사용하기 위함이다.

(이제 PUSH된 BP와 레지스터 BP의 값은 다르다)

 

argument 1

←SP,BP

argument 2

IP(복귀 주소)

BP

 

 

 

 


5. 함수내부에서 스택 사용으로 SP가 증가한다(사용하지 않더라도 상관없다.) 

winapi같은 __stdcall 호출규약을 따르는 프로시저는

사용할 내부변수의 크기를 계산해서

enter x,x 명령어로 sp의 값을 감소시켜준다

(여기선 enter 4,3)

c, c++ 의 __cdecl 호츌규약 프로시저는 수동으로..

argument 1

←BP

←SP

 

argument 2

IP(복귀 주소)

BP

내부변수

내부변수

내부변수

 

 

 


6. 함수에서 복귀를 위해(return) SP를 BP로 되돌린다(SP=BP) 

argument 1

←SP,BP

argument 2

IP(복귀 주소)

BP

내부변수

내부변수

내부변수

 

 

 


7. SP를 되돌렸으면 POP BP를 하여 스택에 저장되어있던 BP를 다시 BP 레지스터에 저장한다.(이로써 함수 호출 이전의 BP 로 돌아온것) 

POP을 했기 때문에 SP가 하나 증가하여 이제 복귀 주소를 가리키고 있다.

argument 1

 

←SP

 

argument 2

IP(복귀 주소)

BP

내부변수

내부변수

내부변수

 

 

 


                                                                                                                     ←SP

8. ret 명령어는 다시 POP IP를 수행한다. 이로써 IP는 저장되어있던 복귀주소 즉 함수호출 CALL nnnn 다음 명령어로 변경된다.

이때 __stdcall을 사용하는 윈도우 프로그램은 ret 뒤의 피연산자로 붙은 4(인자크기 × 인자수)가 SP+4를 수행하여 SP를 4만큼 증가시킨다. (이부분 전체명령어는 ret 4이다. 피호출측에서 스택을 복구 시킨다.)

cdecl을 사용하는 c,c++프로시저는 복귀한뒤에 add, sp+4 를 할 수 있다.(호출측에서 스택을 복구시킨다)

argument 1

 

argument 2

IP(복귀 주소)

BP

내부변수

내부변수

내부변수

 

 

 


                                                                                                                      ←SP

9. 최종적으로 IP는 CALL nnnn의 다음 명령어로 변경되었고 SP또한 함수 호출 이전의 상태로 되돌아 왔다.(스택의 내용을 delete 한 것은 아니지만 스택포인터가 증가되어 앞으로 덮어쓰게 될것이므로 지워진것이나 마찬가지이다.)

argument 1

 

argument 2

IP(복귀 주소)

BP

내부변수

내부변수

내부변수

 

 

 

 32bit 이상 프로세서 에서는 확장 EBP,ESP 등등으로 바뀐다..


winapi 함수는 __stdcall을 쓰며 피호출 함수안에서 스택을 복구 시켜주고 복귀하며

c, c++ 함수는 __cdecl을 쓰며 호출하는 함수에서 피호출함수가 리턴되면 스택을 복구 시킨다.


enter 명령은 (enter n,0)

    push ebp

    mov ebp,esp

    sub esp,n

세개의 명령과 같고


leave명령은

    mov esp,ebp

    pop ebp

명령과 같다.


함수에서 리턴하려면

enter

leave

ret 명령으로 짝을 이루어야 한다.(스택을 피호출 측에서 복구해야 한다면  'ret 매개변수의 총크기')

+ Recent posts