슬기로운 해커 생활

Computer Science

[Computer Science] 메모리 구조(RAM)

Tjdmin1 2023. 5. 7. 00:23

기억 장치는 휘발성 메모리와 비휘발성 메모리로 나뉘어집니다.

휘발성 메모리란 부팅과 동시에 사용되며, 컴퓨터를 종료함과 동시에 모든 OS와 적재된 응용 프로그램 등의 데이터가 사라지게 돼는 기억장치 입니다.

비휘발성 메모리란 휘발성 메모리와는 다르게 컴퓨터가 종료돼도 데이터가 사라지지 않고 계속 저장되는 기억장치를 의미합니다.


휘발성 메모리에는 대표적으로 RAM이 있으며 비휘발성 메모리에는 대표적으로 HDD, SSD, ROM 등이 있습니다.

컴퓨터를 부팅하면 OS가 RAM에 로드되며 그 이후 응용 프로그램을 실행할 때 RAM에 적절하게 공간이 할당되게 됩니다.
또한 컴퓨터를 종료할 경우 RAM에 저장된 데이터가 모두 소멸되며 종료되게 됩니다.
그러나 OS나 실행파일 등은 컴퓨터를 종료시켜도 여전히 비휘발성 메모리인 HDD와 SSD에 남아있습니다.

따라서 비휘발성 메모리에 담겨있는 것은 그저 코드 덩어리라고 할 수 밖에 없습니다.

Reverse Engineering 에서는 RAM에 대한 개념이 중요합니다.
OS는 실행 파일을 RAM에 로드시킬 때 메모리 공간을 할당하게 되는데 Windows의 메모리 공간 구조는 아래 사진과 같습니다.

 

메모리 구조

C언어 자료 구조를 공부해보신 분들이라면 Heap과 Stack은 많이 들어보셨을텐데요.

메모리 구조는 다음과 같습니다.

Code Segment, Data Segment, Heap Segment, Stack Segment가 있습니다.

 

1.Code 영역 (Code Segment)

Text Segment라고도 불리며 실행 할 실행 파일의 코드가 바이너리 형태로 담겨져 있습니다.

PE File과 ASM 언어를 공부하신 분이라면 Section .text랑 같다 보시면 됩니다.

CPU는 Code 영역에 있는 바이너리를 처리합니다.

Register 중 CS Register는 Code Segment의 시작 주소를 저장합니다.

 

2.Data 영역 (Data Segment)

Data 영역은 실행 파일의 전역 변수 혹은 정적 변수의 정보가 담겨져 있습니다.

실행 파일의 시작과 동시에 할당되며 종료와 동시에 해제됩니다.

컴파일 하면 정적 혹은 전역 변수를 참조하는 코드는 전부 Data 영역의 주소 값으로 바뀌게 됩니다.

Linux에는 BSS Segment라는 것이 있는데 Data에는 초기화 된 전역/정적 변수들이 들어가고

BSS에는 초기화 되지 않은 전역/정적 변수들이 들어가며 0으로 값이 할당됩니다.

(상수는 #define과 const로 선언되는 것이 있는데 #define은 Data Segment에 안들어가고 const는 read only data section에 들어갑니다.)

Register 중 DS Register는 Data Segment의 시작 주소를 저장합니다.

 

3.Heap 영역 (Heap Segment)

Heap에는 실행 파일의 동적 할당된 변수들이 들어가게 됩니다.

런타임시 크기가 결정됩니다.

런타임이란 컴파일 후 실행 파일을 시작할 때의 시간을 말합니다.

C언어 에선 malloc, calloc, realloc을 사용해 할당 할 수 있으며 변수를 다 쓴 후 해체해주지 않으면 메모리 누수가 발생하여

실행 파일이 종료 되었음에도 메모리를 계속 점유하여 메모리를 낭비하는 현상이 일어납니다.

따라서 동적 할당 후 헤제를 해야합니다.

Heap은 낮은 주소에서 높은 주소로 향하는 특성이 있습니다.

 

4.Stack 영역(Stack Segment)

Stack에는 실행 파일의 지역변수, 매개변수, Return address 등이 저장됩니다.

컴파일 시에 크기가 결정되며 함수의 호출 시작 시 할당되며 함수가 종료될 시에 해제됩니다.

스택은 LIFO(Last In FIrst Out)형식입니다.

LIFO란 Last-In-First-Out의 약자로 마지막에 들어간 데이터가 첫번째로 꺼내지는 것을 의미합니다.

컴파일 타임에 공간이 할당되므로 무한한 공간이 아니라 재귀함수 등으로 많은 지역변수나 매개변수를 호출하면 스택에서

넘쳐 Stack Overflow가 발생하게 됩니다.

컴파일 타임이란 말 그대로 컴파일을 할 때의 시간입니다.

Stack은 push 동작으로 데이터를 저장하고, pop 동작으로 데이터를 인출합니다.

Stack은 높은 주소에서 낮은 주소로 향하는 특성을 가지고 있습니다.

Register 중 SS Register는 Stack Segment의 시작 주소를 저장합니다.

 

이런 식의 메모리 구조를 가지고 있으며 Reverse Engineering을 할 때 변수 할당 시에 변수의 종류에 따라 다 다른 영역에 분류되므로 메모리 구조를 공부하는 것은 필수라 말할 수 있습니다.

다음 글은 컴파일 과정에 대해 올려보도록 하겠습니다.

컴파일 과정에 대해 알면 #define이 왜 Data Segment에 들어가지 않는지 아시게 될 것입니다.

'Computer Science' 카테고리의 다른 글

[Computer Science] 레지스터(Register)란?  (2) 2023.03.04