1. 스택프레임

// ESP가 아닌, EBP레지스터를 사용하여 스택 내의 로컬 변수, 파라미터, 복귀 주소에 접근하는 기법. 

왜?? ESP는 수시로 변경되기 때문에 ESP를 기준으로 프로그램을 만들면 정확한 위치를 참고할 때 CPU가 힘들어. 


예시>

PUSH EBP  // 함수 시작(EBP를 사용하기 전에 기존의 값을 스택에 저장)

MOV EBP, ESP // 현재 ESP(스택 포인터)를 EBP에 저장 

......

......

MOV ESP, EBP // ESP를 정리 (함수 시작했을 때의 값으로 복원시킴)

POP EBP // 리턴되기 전에 저장해 놓았던 원래 EBP 값으로 복원

RETN  // 함수 종료 




call 02_hello.00401000 // add() 함수 



PUSH EBP // EBP값을 스택에 넣어라. EBP가 메인함수에서 베이스 포인터의 역할을 하게 되니깐 EBP가 이전에 갖고 있던 값을 스택에 백업하기 위한 용도
MOV EBP,ESP // ESP의 값을 EBP로 옮겨라. 즉, EBP는 ESP와 같은 값을 갖게됨.
SUB ESP,8 // long은 4byte이며, a,b 2개이므로 8byte의 공간 확보
MOV DWORD PTR SS:[EBP-4],1 // a의 1을 [EBP-4]에 저장.
MOV DWORD PTR SS:[EBP-8],2 // b의 2를 [EBP-8]에 저장.
MOV EAX,DWORD PTR SS:[EBP-8] // [EBP-8]주소에서 4byte 크기의 메모리 내용을 EAX로 이동
PUSH EAX // b에 값인 2를 스택에 넣기
MOV ECX,DWORD PTR SS:[EBP-4] // [EBP-4]주소에서 4byte 크기의 메모리 내용을 ECX로 이동
PUSH ECX // a에 값인 1을 스택에 넣기
CALL 02_hello.00401000 // add()함수
ADD ESP,8
PUSH EAX ; /<%d>
PUSH 02_hello.004020F4 ; |format = "%d
"
CALL DWORD PTR DS:[<&MSVCR90.printf>] ; \printf
ADD ESP,8 // 스택공간 정리 (파라미터 a,b관련 공간)
XOR EAX,EAX // 리턴값을 받는 EAX 초기화
MOV ESP,EBP // 함수의 에필로그
POP EBP
RETN


< CALL 02_hello.00401000 >

PUSH EBP // main() 함수에서 사용되던 EBP값을 스택에 백업
MOV EBP,ESP // add() 함수의 프롤로그
SUB ESP,8 // 스택에 8byte의 공간확보 (로컬변수 a,b의 공간)
MOV EAX,DWORD PTR SS:[EBP+8] // 파라미터 a를 가리킴
MOV DWORD PTR SS:[EBP-8],EAX // a의 값인 1을 [EBP-8]에 넣음
MOV ECX,DWORD PTR SS:[EBP+C] // 파라미터 b를 가리킴
MOV DWORD PTR SS:[EBP-4],ECX // b의 값인 2를 [EBP-4]에 넣음
MOV EAX,DWORD PTR SS:[EBP-8] // 1을 EAX에 넣음
ADD EAX,DWORD PTR SS:[EBP-4] // EAX에 2를 더해서 EAX는 3이 됨
MOV ESP,EBP // ESP를 원래대로 복원 (함수가 시작할때 ESP의 값을 EBP에 넣어두었다가 함수가 종료될 때 ESP를 원래대로 복원시키는 목적)
POP EBP





+ Recent posts