내장형 하드웨어/C언어

assembler - stack의 이해 (ebp, esp, eip)

동화다아아 2011. 4. 27. 13:46

#include<stdio.h>

void test(int A, int B);

int main()

{

        int A;

        int B;


        printf(" &A: %08X\n &B: %08X\n",&A,&B);

        test(A,B);

        return 0;

}

void test(int A, int B)

{

        int C;

        int D;

        printf(" &A: %08X\n &B: %08X\n",&A,&B);

        printf(" &C: %08X\n &D: %08X\n",&C,&D);

        

        return ;

}

⇒ 실행 결과

        


⇒ main함수

 → &A는 0012FF7C

 → &B는 0012FF78

⇒ test함수

 → &A는 0012FF24

 → &B는 0012FF28

 → &C는 0012FF18

 → &D는 0012FF14

⇒ 변수는 처음부터 뒤로 생성(메모리)

⇒ 인자는 뒤에서부터 앞으로 생성(메모리)

⇒ test 인자변수와 (A,B), 변수(C,D) 사이에 윈도우와 리눅스 공통으로 8byte의 공간이 비어있다.

- stack 에서의 메모리 확인


⇒ 실행 결과

        

 


 

 

 

 

test함수

9C

D=6

← 변수

06

00

00

00

100

C=5

05

00

00

00

104

 

 

5C

F8

FF

BF

108

 

 

4D

84

04

08

10C

A=4

← 인자변수

 

 

B=3

 

 

 

 

 

main함수

B=2

← 변수

 

A=1

 


- stack 구조 (CD를 중앙 기둥에 넣어 쌓는 큰 공CD 케이스를 생각해 보자.)

        

 

H

G

F

E

D

C

B

A

⇒ A를 꺼내려면 B~H까지를 다 꺼내야 한다.

⇒ 최근 변수가 위로 올라간다. → LIFO(Last-Input First-Out : 나중에 입력된 데이터가 출력 명령을 받을 때 가장 먼저 출력된다. - 후입선출)

⇒ stack의 제일 아래를 base, 최상위를 top.

⇒ 즉, base와 top은 주소를 가르키므로 base pointer, stack point, BP, SP 라고 한다.

⇒ intel은 처음 16bit 였으므로 2byte의 버스와 메모리 주소를 가졌으나, 현재는 32bit를 주로 사용하므로 버스와 메모리 주소가 4byte 이므로 확장된 BP, SP라 부른다.

⇒ Extend BP, Extend SP → EBP, ESP


main stack은 EBP와 ESP 에 싸여있다.


잠시 가정을 해서 만약 ebp=1004; 라고 한다면(ebp가 C의 포인터라면)

esp=ebp;

 push A (→ 어셈블리 명령)

 → 여기서 push A는 esp = esp-4;와 *esp = A;의 뜻을 가진다.

⇒ esp는 밀어 넣을 때(push) 항상 그 자리에 있다.

⇒ pop은 꺼낼 때 (→ pop을 할 때는 꺼낸것을 어디에 집어넣을지 결정해야 한다.)

 pop K

 → 여기서 popk는 k = *esp;와 esp = esp+4; 의 뜻

⇒ pop과 push는 순서가 다르다.(stack operation)


⇒ 처음에는 ebp와 esp의 위치가 같으나 push 될 때 esp가 한칸씩 올라간다.

⇒ call test → test 함수 호출 명령

   push 3

   push 4

   call test

 → 이 세줄이 C 언어의 test(4,3); 과 같다.


※ 프로그램 실행 : main 함수의 주소를 eip에 집어 넣는 것

   return address





※ 참고(함수 호출 시 stack 구조 - http://byunhy69.blog.me/140112048445)

- ESP : 함수가 진행하고 있을 때  stack의 제일 아래 부분,현재 진행 stack 지점, Stack Pointer

          stack 메모리는 아래로 성장하기 때문에 제일 아래가 제일 마지막이 된다.


- EBP : 스택의 가장 윗 부분(기준점), Base Pointer

- EIP : 실행할 명령의 주소, Instruction Pointer

- E가 붙는 것은 16비트에서 32비트 시스템으로 오면서 Extended 된 개념, 64비트에서는 R이 붙음

- 32bit 레지스터의 기본 설명은 http://www.reversecore.com/tag/EIP 참고

- Context Switching :  Multi-Tasking상황에서 현재 작업을 진행하고 있는 CPU의 각 register들의 정보가 저장되고 이전 것이 다시 불려지면서 교환되는 상황.

⇒ ESP 는 스택 메모리 주소를 가리킵니다. 어떤 명령어들(PUSH, POP, CALL, RET) 은 ESP 를 직접 조작하기도 합니다. (스택 메모리 관리는 프로그램에서 매우 중요하기 때문에 ESP 를 다른 용도로 사용하지 않는것이 좋습니다.)

⇒ EBP 는 함수가 호출되었을때 그 순간의 ESP 를 저장하고 있다가, 함수가 리턴하기 직전에 다시 ESP 에 값을 되돌려줘서 스택이 깨지지 않도록 합니다. (이것을 stack frame 기법이라고 하며, 나중에 따로 설명할 예정입니다.)


ESI 와 EDI 는 특정 명령어(LODS, STOS, REP MOVS, etc)와 함께 주로 메모리 복사에 사용됩니다.