전체 코드


1. 스택 메모리 개요

스택 메모리는 후입선출(LIFO, Last In First Out) 구조로 되어 있으며, 함수 호출 시 다음과 같은 요소들이 저장됩니다.

  • 리턴 주소(Return Address): 함수가 종료될 때 복귀할 위치.
  • 저장된 레지스터 값: 함수 호출 전에 레지스터 값을 저장하여 이후 복원.
  • 매개변수(Arguments): 함수로 전달되는 인자.
  • 지역 변수(Local Variables): 함수 내에서 선언된 지역 변수.

함수가 호출되면 새로운 스택 프레임(Stack Frame) 이 생성되고, 함수가 종료되면 해당 스택 프레임이 해제됩니다.


2. 스택 프레임의 구조

스택은 높은 메모리 주소에서 낮은 메모리 주소 방향으로 성장하며, 함수가 호출될 때마다 새로운 스택 프레임이 생성됩니다.

스택 프레임 예시

#include <iostream>
using namespace std;

void Func3(float a) {
    cout << "Func3" << endl;
}

void Func2(int a, int b) {
    cout << "Func2" << endl;
    Func3(10);
}

void Func1() {
    cout << "Func1" << endl;
    Func2(1, 2);
}

int main() {
    cout << "main" << endl;
    Func1();
    return 0;
}

3. 스택 프레임이 생성되는 과정

위 코드를 실행할 때 스택 프레임이 어떻게 생성되고 관리되는지 어셈블리 코드를 분석하여 확인해보겠습니다.

1️⃣ 매개변수 전달 및 스택 저장

00312711  mov         eax,dword ptr [b]
00312714  push        eax  
00312715  mov         ecx,dword ptr [a]  
00312718  push        ecx
  • ba 변수를 push 명령어를 통해 스택에 저장.
  • 이를 통해 MultiplyBy 함수의 매개변수로 사용될 수 있도록 준비됨.

2️⃣ 함수 호출 및 리턴 주소 저장

00312719  call        MultiplyBy (0311118h)
  • MultiplyBy 함수 호출 (call 명령어).
  • 호출 시 현재 실행 위치(리턴 주소)를 스택에 저장하고 MultiplyBy 함수로 이동.

3️⃣ 스택 프레임 정리

0031271E  add         esp,8
  • 함수 종료 후, esp를 조정하여 스택에서 인자 해제 (8바이트 해제, int 2개).

4️⃣ 함수 종료 및 리턴

00312736  mov         esp,ebp  
00312738  pop         ebp  
00312739  ret
  • ebp를 복원하여 스택 프레임 해제.
  • ret 명령어 실행 후, 저장된 리턴 주소로 복귀.

4. 스택 프레임 디버깅

디버깅을 활용하여 함수 호출 과정에서 스택의 변화를 추적할 수 있습니다.

디버깅 명령어

설명
F5디버깅 시작
F10함수 실행 결과만 확인
F11함수 내부 코드까지 한 단계씩 실행

5. 스택 프레임 시각적 분석

(1) 매개변수 저장

  • push 명령어를 통해 ab 값이 스택에 저장됨.
ESP 주소데이터
0x00AFF744b = 5
0x00AFF740a = 3

(2) 리턴 주소 저장

  • 함수 호출 (call MultiplyBy) 직후, 리턴 주소가 스택에 저장됨.
ESP 주소데이터
0x00AFF73C리턴 주소 (0x007B2690)
0x00AFF740a = 3
0x00AFF744b = 5

(3) 지역 변수 저장

int MultiplyBy(int a, int b) {
    int c = a * b; // 지역 변수 c
    return c;
}
  • c의 값이 계산되고 스택에 저장됨.
ESP 주소데이터
0x00AFF738지역 변수 c = 15
0x00AFF73C리턴 주소
0x00AFF740a = 3
0x00AFF744b = 5

(4) 함수 종료 및 리턴

  • pop 명령어를 사용하여 스택을 정리하고, ret을 실행하여 원래 실행 위치로 복귀.

6. 스택 프레임과 레지스터 활용

1️⃣ ESP (Stack Pointer)

  • 현재 스택의 최상단 주소를 가리킴.
  • push 시 감소, pop 시 증가.

2️⃣ EBP (Base Pointer)

  • 함수 실행 중 스택 프레임의 기준 주소 역할.
  • ebp를 사용하여 매개변수와 지역 변수 접근.

3️⃣ 함수 호출 시 레지스터 변화

  • ESP는 계속 변하지만 EBP는 상대 주소 계산을 위해 고정됨.

7.디버깅

  1. Ctrl + Alt + G: 레지스터 창 열기.
  2. ESP 값을 복사하여 메모리 주소 입력 후 스택 확인.
  3. F11을 사용하여 한 줄씩 실행하며 데이터 변화를 관찰.

이 자료를 바탕으로 다시 학습하면 스택 프레임과 함수 호출의 원리를 확실히 이해할 수 있습니다! 🚀

profile
李家네_공부방

0개의 댓글