Virtual Memory 심화 이론

💡
Basic Assembly의 범위를 넘어선 학습내용 정리.

가상 메모리(VM)레이아웃의 상세 특성

1. 커널 영역 (Kernel Space)

  • 주소 범위: 0xFFFF800000000000 ~ 0xFFFFFFFFFFFFFFFF
  • 특징:
    • 사용자 프로그램에서 직접 접근 불가
    • 시스템 호출을 통해서만 간접 접근
    • 모든 프로세스가 동일한 커널 공간을 공유
  • 용도: 운영체제 코드, 디바이스 드라이버, 시스템 자료구조

2. 스택 (Stack)

  • 주소 범위: 0x00007FFFFFFFFFFF부터 아래로 성장
  • 특징:
    • 함수 호출 시 자동으로 할당/해제
    • LIFO (Last In, First Out) 구조
    • 스택 포인터(RSP)가 현재 위치 가리킴
    • 스택 오버플로우 시 세그멘테이션 폴트 발생
; 함수 호출 시 스택 구조
[RSP + 0]  ← 지역변수
[RSP + 8]  ← 이전 RBP (베이스 포인터)
[RSP + 16] ← 반환 주소
[RSP + 24] ← 매개변수

3. 힙 (Heap)

  • 주소 범위: BSS 영역 위부터 위로 성장
  • 특징:
    • 동적 메모리 할당 (malloc, calloc, new)
    • 프로그래머가 명시적으로 관리
    • 메모리 누수 가능성 존재
    • 단편화 문제 발생 가능
  • 시스템 호출: brk(), sbrk(), mmap()

4. BSS 영역 (Block Started by Symbol)

  • 특징:
    • 초기화되지 않은 전역/정적 변수
    • 프로그램 로딩 시 0으로 초기화
    • 실행 파일에는 크기 정보만 저장 (공간 절약)
int global_array[1000];        // BSS 영역
static int static_var;         // BSS 영역

C Language

5. 데이터 영역 (.data)

  • 특징:
    • 초기화된 전역/정적 변수
    • 읽기/쓰기 가능
    • 실행 파일에 초기값이 포함됨
int global_var = 100;          // 데이터 영역
static int static_var = 200;   // 데이터 영역

C Language

6. 코드 영역 (.text)

  • 특징:
    • 실행 가능한 기계어 코드
    • 읽기 전용 (Execute/Read, No Write)
    • 코드 인젝션 공격 방지
    • 여러 프로세스가 공유 가능

메모리 레이아웃의 심화

1. 현대의 메모리 구조가 생겨난 배경

역사적 배경

  • Segmentation: 초기 8086에서 64KB 제한을 극복하기 위해
  • Paging: 가상 메모리와 메모리 보호를 위해 도입
  • ASLR (Address Space Layout Randomization): 보안 강화를 위한 현대적 기법

설계 원칙

분리의 원칙: 코드 ↔ 데이터 ↔ 스택을 물리적으로 분리
보안의 원칙: 실행 가능한 영역은 쓰기 금지 (NX bit)
효율의 원칙: 자주 사용되는 영역을 가까이 배치

2. 메모리 보호와 보안

NX bit (No eXecute or Never eXecute)

# 메모리 영역별 권한 확인
$ cat /proc/self/maps
400000-401000 r-xp ... /program    # 코드: 실행가능, 쓰기불가
600000-601000 rw-p ... /program    # 데이터: 읽기쓰기, 실행불가
7fff-7fff r--p ... [vvar]          # 가상 변수 페이지

ASLR (Address Space Layout Randomization)

# ASLR 상태 확인
$ cat /proc/sys/kernel/randomize_va_space
2  # 모든 영역 랜덤화

# 같은 프로그램을 여러 번 실행해도 주소가 다름
$ ./program & echo "PID: $!"; cat /proc/$!/maps | head -5
$ ./program & echo "PID: $!"; cat /proc/$!/maps | head -5

3. 스택과 힙의 충돌

스택 오버플로우

recursive_function:
    push rbp
    mov rbp, rsp
    sub rsp, 1000               ; 큰 지역변수 할당
    
    call recursive_function     ; 무한 재귀
    
    add rsp, 1000
    pop rbp
    ret
    ; 결과: 스택이 힙 영역을 침범하여 세그폴트 발생

힙 고갈

// 메모리 누수로 인한 힙 고갈
while(1) {
    void* ptr = malloc(1024*1024);  // 1MB 할당
    // free(ptr); 를 하지 않음 → 메모리 누수
}

4. 실무에서의 활용

성능 최적화

; 지역성 원리 활용 (Locality of Reference)
; 스택 변수들은 가까이 위치하므로 캐시 효율이 좋음
process_array:
    sub rsp, 32                 ; 지역변수들을 스택에 연속 배치
    mov [rsp + 0], rax         ; temp1
    mov [rsp + 8], rbx         ; temp2  
    mov [rsp + 16], rcx        ; temp3
    mov [rsp + 24], rdx        ; temp4
    ; 이들은 같은 캐시 라인에 있을 가능성이 높음

디버깅과 프로파일링

# 메모리 사용량 실시간 모니터링
$ pmap -x PID
Address  Kbytes RSS   Dirty Mode  Mapping
00400000    4    4     0 r-x--  /program
00600000    4    4     4 rw---  /program
...

5. 운영체제별 차이점

항목Linux x86-64Windows x64macOS x86-64
코드 시작0x4000000x1400000000x100000000
스택 크기8MB (기본)1MB (기본)8MB (기본)
ASLR기본 활성화기본 활성화기본 활성화
스택 방향아래로 성장아래로 성장아래로 성장

핵심 포인트

  1. 메모리 영역은 각각 다른 목적과 특성을 가짐
  2. 보안을 위해 코드 영역은 읽기 전용으로 설정
  3. 스택과 힙이 서로 반대 방향으로 성장하여 공간을 효율적으로 사용
  4. ASLR과 NX bit 같은 현대적 보안 기법이 이 구조를 활용
  5. 어셈블리 프로그래밍 시 각 영역의 특성을 고려해야함

고급 주소 지정과 메모리 모델

; 세그먼트 레지스터 활용 (실제 시스템에서 중요)
mov ax, ds:[bx + si]        ; 데이터 세그먼트 접근
mov ax, es:[di]             ; 추가 세그먼트 접근

; 메모리 모델별 차이점 (small, medium, large, huge)
; 실제 보호모드 vs 리얼모드 차이점

고급 산술 연산

; 128비트 정밀도 연산
mov rax, 0xFFFFFFFFFFFFFFFF
mov rdx, 0xFFFFFFFFFFFFFFFF
add rax, 1                   ; 다정밀도 덧셈
adc rdx, 0                   ; 캐리 전파

; BCD 연산 (Binary Coded Decimal)
daa                          ; decimal adjust after addition
das                          ; decimal adjust after subtraction

고급 비트 조작

; 비트 스캔 연산
bsf rax, rbx                 ; bit scan forward
bsr rax, rbx                 ; bit scan reverse
popcnt rax, rbx              ; population count (1비트 개수)

; 조건부 이동 (Pentium Pro+)
cmov rax, rbx                ; conditional move

메모리 구조를 깊이 있게 이해할수록 버퍼 오버플로우, 메모리 누수, 성능 최적화 등의 다양한 이슈 발생시 골머리를 앓지 않아도 된다.