메모리 영역 (Code, Data, BSS, HEAP, Stack), Little Endian, Stack의 이해
- 메모리 영역 (윈도우 기준, 리눅스는 조금 다르다.)
함수, 제어문, 상수 등등 / 함수에 대한 기계어 코드가 들어감 |
← |
Code |
compile time에 크기가 결정되고 이후로 변동되지 않는다. |
전역변수 / 초기값 있는 전역변수, 배열, static으로 선언된 변수가 들어감 |
← |
Data | |
전역변수 / 초기값 없는 전역변수, 배열, static으로 선언된 변수가 들어감 |
← |
BSS | |
동적할당 / 동적할당(malloc)으로 할당된 변수가 들어감 |
← |
HEAP |
run time에 BSS와 HEAP사이를 기준으로 해서 heap은 아래로 순차적으로 메모리를 사용하고 stack은 위쪽으로 순차적으로 메모리를 사용한다. |
지역변수 / 블록내에서 할당된 변수가 들어감 |
← |
STACK |
⇒ 프로그램을 작성하면 code 영역이 늘어난다.
⇒ stack(지역변수)을 프로그램 하면서 얼마나 사용할 지 미리 계산할 수 없다. 그래서 stack 함수의 뒷부분에서부터 변수의 주소가 매겨진다.(code는 0에서 stack FFFFFFFF까지 메모리 값을 가진다. - 반드시 STACK이 FFFFFFFF부터의 주소를 가지는게 아니라 그 근처에서 메모리 값을 가진다.) 즉, 변수 선언 순서에 따라 높은 주소에서 낮은 주소로 내려간다.
⇒ compile time에 code, data, bss는 크기가 결정되며 고정된다.
⇒ run time 때 Heap과 stack의 메모리 사용이 결정되는데 heap는 bss와의 경계에서 아래로 stack은 끝에서부터 위로 주소값을 메긴다.
⇒ code를 작성하면,
if(……) → ASM → 기계어 → 기계어가 code에 채워진다.
int A; → stack에 4byte 공간을 만들어라는 뜻.
⇒ 실행파일에는 A가 없고, A를 만들라는 지시가 있다. A는 실행시킬 때 생성된다.
⇒ hard disk에 code, data, bss가 들어있다.(실행파일 안에-.exe)
⇒ 실행파일을 실행하면 bss가 메모리에 들어가 stack 시작점을 생성하고 코드를 읽어들인다.
⇒ 로더 : 적제기, 로딩(메모리에 올린다.)
#include<stdio.h>
int main()
{
int A=0x12345678;
int B=0x9ABCDEF0;
int C;
printf("&A: %08X\t &B: %08X\t &C: %08X\n",&A,&B,&C);
printf("main: %08X\n", main);
printf("printf: %08X\n", printf);
printf("scanf: %08X\n", scanf);
return 0;
}
⇒ A, B, C의 주소값을 확인해 보면 little Endian 으로 저장되고 있음을 확인할 수 있다.
symbol table
type |
name |
address |
int |
A |
BFFFF868 |
int |
B |
BFFFF864 |
int |
C |
BFFFF860 |
little Endian |
78 |
56 |
34 |
12 |
|
68 |
69 |
6A |
6B |
little Endian |
F0 |
DE |
BC |
9A |
|
64 |
65 |
66 |
67 |
⇒ int A, int B, int C의 순서대로 선언되었으나 메모리 값은 반대의 순서로 되어있다?
⇒ 상수 → 변화하지 않는 수, 변수 → 변하는 수(Data, BSS, STACK - 지금까지 써온 변수들)
⇒ main도 주소를 가진다. (&를 붙이지 않아도 주소값이 나온다.→printf,scanf...들도 마찬가지)
⇒ 출력결과
symbol table
type |
name |
address |
|
main |
08048400 |
|
printf |
08048300 |
|
scanf |
08048304 |
#include<stdio.h>
int main()
{
int A=0x12345678;
int B=0x9ABCDEF0;
char G;
short F;
char C;
short E;
int D;
printf("&A:%08X\n &B:%08X\n &C:%08X\n &D:%08X\n &E:%08X\n &F:%08X\n &G:%08X\n", &A, &B, &C, &D, &E, &F, &G);
return 0;
}
⇒ 실행결과
⇒ 각 변수의 주소값의 메모리 위치 확인을 통한 stack 함수의 이해
54 |
55 |
56 |
57 |
58(D) |
59 |
5A |
5B |
5C |
5D |
5E(E) |
5F |
60(F) |
61 |
62(G) |
63(C) |
64(B) |
65 |
66 |
67 |
68(A) |
69 |
6A |
6B |
⇒ stack 의 특징(intel cpu)
1) 4byte 단위로 쪼갠다.
→ 즉, BUS에 최적화
2) 4byte가 안되면 2byte 단위
3) 그 다음으로 1byte 단위
⇒ 프로그램을 잘 짜려면 stack 을 잘 맞추어 주어야 한다. 물론 16bit 에서는 소용없다.
⇒ 우리의 컴은 대부분 32bit 이므로 컴파일러도 32bit 기준으로 stack 작성
⇒ 컴파일러가 16bit 용이라면 cpu가 32bit라도 16bit에 맞추어 stack 주소 작성
'내장형 하드웨어 > C언어' 카테고리의 다른 글
visual studio 6.0 debug mode - stack (esp, sbp, eip) (0) | 2011.04.28 |
---|---|
assembler - stack의 이해 (ebp, esp, eip) (0) | 2011.04.27 |
NASM, MASM 설치, 함수 (실인수, 형식인수, 지역변수) (0) | 2011.04.25 |
#define, 함수 인자, 반환(return, printf) (0) | 2011.04.22 |
makefile 사용방법(rm, -rf, echo, @), linux 용어(sshd,server,client,path,set), ATmega makefile 분석 (3) | 2011.04.21 |