본문으로 바로가기



스택 프레임이란?


함수가 호출되었을 때 해당 함수가 가지는 공간 구조를 말한다




스택 프레임의 구조


LIFO 구조로 쌓이며 괄호로 이야기 하면 더 쉬울것 같다


[ { ( [ [ ] ] ) } ]


이처럼 좌우 대칭이 되는 구조라고 생각하면 될것 같다


개략적으로 나타내면


push func_one()

push func_two()

pop func_two()

pop func_one()


위와 같고 실제로 어셈블리어에서는 다음과 같은 구조를 띈다



push ebp ---> 현재 ebp를 스택에 저장해놓는다

mov ebp, esp ---> ebp를 최상단으로 옮긴다


. . . ---> 새로운 함수의 내용


mov esp, ebp ---> esp값을 복원(위의 코드엔 없음)

pop ebp ---> 저장해놓았던 ebp값을 복원

ret ---> 함수 종료






함수 호출시 형성되는 구조인 스택 프레임에 대해 알아보았다


 그렇다면 실제로 함수 호출 과정은 어떻게 이루어질까?



함수가 필요로 하는 파라미터를 스택에 넣는다


함수 시작지점으로 점프한다(호출)


함수 내에서 사용할 스택 프레임을 구성한다(프롤로그)


함수 내용을 수행한다


수행을 마치고 스택을 복원하여 함수 호출 전 위치로 돌아간다(에필로그)



위에서 공부한 스택 프레임을 사용하여 프롤로그와 에필로그가 구성이 된다


하지만 이러한 프롤로그와 에필로그는 함수 호출 규약에 따라 조금씩 달라진다






함수 호출 규약이란?


함수 호출이 끝난 후 스택을 처리하는 방법에 대한 약속이다


에필로그의 종류라 봐도 될것같다



cdecl


주로 C언어에서 사용되며 함수를 호출한 곳에서 스택이 정리된다


가변 길이 파라미터를 전달할 수 있다는 장점이 있다


함수 이름 앞에 언더바(_)를 추가하는 특징을 갖는다


(ex function abc ---> _abc)





stdcall


win32 API에 주로 사용되며 호출받은 곳에서 스택이 정리된다


가변인자를 전달하는것이 불가능하나 함수호출 후에 스택정리를 하지 않아 속도면에서 빠르다는 장점이 있다


함수명 앞에 언더바를 붙이고 뒤에는 @를 붙인 후 매개변수의 전체 바이트수를 10진수로 표기하는것이 특징이다


(ex function abc ---> _abc@8)





fastcall


파라미터의 마지막 2개는 스택이 아닌 레지스터(ecx, edx)에 저장하여 전달되며 호출받은 곳에서 스택이 정리된다


빠른 함수 호출이 가능하지만 해당 레지스터에 민감한 데이터가 포함되어있거나 다른 목적이 존재한다면


파라미터를 따로 저장해야한다는 단점이 있다


함수명 앞과 뒤에 @를 붙이고 매개변수 크기를 10진수로 표기하는것이 특징이다


(ex function abc ---> @abc@8)







이 외에도 thiscall, naked와 같은 규약도 있다