[스택 프레임 전체 흐름]



[어셈블리 수준에서의 설명]

//원래 소스 코드
void Swap(int *parm_a, int *parm_b)
{
    int temp = 0;
    // temp 변수를 이용하여 parm_a와 parm_b의 포인터 값을 바꾼다.
    temp = *parm_a;
    *parm_a = *parm_b;
    *parm_b = temp;
}
void main()
{
    int a = 5, b = 7;
    
    // 변수 a와 b의 값을 바꾼다.
    Swap(&a, &b);
    a += 3;
    b += 4;
}
 
 
 
//어셈 코드
void Swap(int *parm_a, int *parm_b)
{
00FA16A0  push        ebp          //main의 스택 베이스 포인터를 저장한다, swap 함수가 끝나면 다시 main 함수의 스택주소 
                                   // 구간으로 이동하기 위함 여기 까지 하면 EIP, 이전 EBP 가 스택에 싸여 있게 되고
00FA16A1  mov         ebp,esp      //ebp 를 현재 함수의 스택 주소 구간으로 변경하기 위해서 현재 스택포인터 값을 베이스 포인터 값으로 바꿔준다
00FA16A3  sub         esp,0CCh  
00FA16A9  push        ebx          //edx,esi,edi 빽업
00FA16AA  push        esi                       
00FA16AB  push        edi  
00FA16AC  lea         edi,[ebp-0CCh]  
00FA16B2  mov         ecx,33h  
00FA16B7  mov         eax,0CCCCCCCCh          // 변수 공간으로 사용할 해당 구간을  CCCCCCCC 값으로 초기화 해준다
00FA16BC  rep stos    dword ptr es:[edi]      //
    int temp = 0;
00FA16BE  mov         dword ptr [temp],0  
    temp = *parm_a;
00FA16C5  mov         eax,dword ptr [parm_a]  
00FA16C8  mov         ecx,dword ptr [eax]  
00FA16CA  mov         dword ptr [temp],ecx  
    *parm_a = *parm_b;
00FA16CD  mov         eax,dword ptr [parm_a]  
00FA16D0  mov         ecx,dword ptr [parm_b]  
00FA16D3  mov         edx,dword ptr [ecx]  
00FA16D5  mov         dword ptr [eax],edx  
    *parm_b = temp;
00FA16D7  mov         eax,dword ptr [parm_b]  
    *parm_b = temp;
00FA16DA  mov         ecx,dword ptr [temp]  
00FA16DD  mov         dword ptr [eax],ecx  
}
00FA16DF  pop         edi           //함수가 끝때날 edi,esi,edx 를 pop한다
00FA16E0  pop         esi  
00FA16E1  pop         ebx  
00FA16E2  mov         esp,ebp       //스택포인터를 main 의 스택 포인터 구간으로 되돌려주어 main 함수를 계속 수행해나갈 준비를 한다
00FA16E4  pop         ebp           //swap 함수가 끝났음으로 swap 에 대한 스택공간이 필요 없됐음으로 swap 에 대한 pop ebp을 수행
//pop 명령어는 ebp 에 현재 스택 상단의 내용을 ebp 에 넣고 스택을 줄인다는 것인데, 이것은
//이전 main 함수의 스택 포인터 기준 영역으로 되돌아 간다는 의미가 된다
00FA16E5  ret           //이 함수가 콜 되면서 저장해 놓았던 이전 EIP 즉 main 의 다음 실행 주소로 복귀한다(해당 번지로 점프 하는 효과가 발생)
.......
void main()
{
00FA1700  push        ebp  
00FA1701  mov         ebp,esp  
00FA1703  sub         esp,0DCh  
00FA1709  push        ebx  
00FA170A  push        esi  
00FA170B  push        edi  
00FA170C  lea         edi,[ebp-0DCh]  
00FA1712  mov         ecx,37h  
00FA1717  mov         eax,0CCCCCCCCh  
00FA171C  rep stos    dword ptr es:[edi]  
00FA171E  mov         eax,dword ptr [__security_cookie (0FA8004h)]  
00FA1723  xor         eax,ebp  
00FA1725  mov         dword ptr [ebp-4],eax          
//메모리 할당은 작은 주소 순으로 주소가 배열되며 지역변수는 ebp 주소를 기준으로 상대적으로 변수를 할당/사용한다
    int a = 5, b = 7;
00FA1728  mov         dword ptr [a],5  
00FA172F  mov         dword ptr [b],7  
    
    Swap(&a, &b);                                    
00FA1736  lea         eax,[b]                          //swap 에 담길 인자를 스택에 넣는다
00FA1739  push        eax  
00FA173A  lea         ecx,[a]  
00FA173D  push        ecx  
00FA173E  call        Swap (0FA10F5h)                  // swap 을 call 하면서 다음 실행 주소 EIP:00FA1743  를 스택에 push 한다
00FA1743  add         esp,8  
    a += 3;
00FA1746  mov         eax,dword ptr [a]  
    a += 3;
00FA1749  add         eax,3  
00FA174C  mov         dword ptr [a],eax  
    b += 4;
00FA174F  mov         eax,dword ptr [b]  
00FA1752  add         eax,4  
00FA1755  mov         dword ptr [b],eax  
}
00FA1758  xor         eax,eax  
00FA175A  push        edx  
00FA175B  mov         ecx,ebp  
00FA175D  push        eax  
00FA175E  lea         edx,ds:[0FA178Ch]  
00FA1764  call        @_RTC_CheckStackVars@8 (0FA1253h)  
00FA1769  pop         eax  
00FA176A  pop         edx  
00FA176B  pop         edi  
00FA176C  pop         esi  
00FA176D  pop         ebx 


반응형

+ Recent posts