assembler - stack의 이해 (ebp, esp, eip)
#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)와 함께 주로 메모리 복사에 사용됩니다.
'내장형 하드웨어 > C언어' 카테고리의 다른 글
stack 구조, 어셈블리 (MASM, 코드 분석) (0) | 2011.04.29 |
---|---|
visual studio 6.0 debug mode - stack (esp, sbp, eip) (0) | 2011.04.28 |
메모리 영역 (Code, Data, BSS, HEAP, Stack), Little Endian, Stack의 이해 (1) | 2011.04.26 |
NASM, MASM 설치, 함수 (실인수, 형식인수, 지역변수) (0) | 2011.04.25 |
#define, 함수 인자, 반환(return, printf) (0) | 2011.04.22 |