메모리 주소
메모리 주소(Memory Address)란 컴퓨터 과학과 컴퓨터 아키텍처에서, 컴퓨터의 주 기억장치(메인 메모리) 내의 특정 저장 위치를 가리키는 고유한 식별자(identifier)이다. 메모리 주소는 CPU와 메모리 간 데이터 전송의 핵심적인 개념으로, 컴퓨터 프로그램이 데이터를 읽거나 쓸 때 반드시 참조하는 값이다.
현대 컴퓨터 시스템에서는 주로 이진수 형태의 정수로 표현되며, 프로그램 실행 중 변수나 명령어 등의 위치를 찾기 위해 사용된다. 메모리 주소는 하드웨어 레벨뿐만 아니라 운영체제, 프로그래밍 언어, 컴파일러, 링커, 로더 등 소프트웨어 수준에서도 매우 중요한 역할을 한다.
목차
[숨기기]개요[편집]
컴퓨터 과학에서 메모리 주소(memory address)는 메모리 위치에 대한 식별자로, 컴퓨터 프로그램이나 하드웨어 장치가 데이터를 저장하고 나중에 이를 가져오는 장소이다. 일반적으로 이는 이진 형태의 숫자로 되어 있다.
컴퓨터 프로그램에서 절대 주소는 메모리 위치를 식별하는 메모리 고유 주소이다. 즉, 기억장치 고유의 번지로서, 기억장치 중 기억장소를 직접 숫자로 지정하는 주소역할을 한다. 기계어 정보가 기억되어 있으며, 1,2,3,4…와 같이 16진수로 약속하여 순서대로 결정한다. 반면 상대 주소는 고유 주소가 아니며, 특정 영역에 상대적인 주소를 지정한다.
- 기본 개념
메모리 주소는 메모리 내 특정 위치를 나타내는 값이다. 메모리는 연속적인 바이트(8비트) 블록으로 구성되며, 각 바이트는 고유한 주소를 가진다. 이를 통해 CPU는 저장된 데이터를 정확히 찾아서 읽거나 쓸 수 있다.
예를 들어, 주소 0x0000 0000 은 메모리의 가장 처음 위치를, 0x0000 0004 는 그로부터 4바이트 떨어진 메모리 공간을 의미한다.
메모리 주소는 하드웨어의 아키텍처에 따라 주소 길이(주소폭)가 결정된다. 32비트 시스템에서는 32비트 주소를 사용하여 최대 4GB(2³² 바이트) 메모리를 지정할 수 있고, 64비트 시스템에서는 64비트 주소를 사용하여 이론적으로 16엑사바이트(2⁶⁴ 바이트)까지 접근이 가능하다.
주소 지정 방식 (Addressing Modes)[편집]
메모리에 접근하는 방법에는 여러 가지 주소 지정 방식이 존재한다. 이는 CPU가 명령어를 통해 메모리에 접근할 때 어떤 식으로 주소를 계산하는지를 정의한다.
- 즉시 주소 지정 (Immediate Addressing)
명령어에 값이 직접 포함된다. 주소가 아니라 값 자체를 사용한다.
asm MOV AX, 5 ; 5를 AX 레지스터에 저장
- 직접 주소 지정 (Direct Addressing)
명령어에 메모리 주소가 포함된다.
asm MOV AX, [1234h] ; 메모리 주소 0x1234의 값을 AX에 저장
- 간접 주소 지정 (Indirect Addressing)
레지스터에 저장된 값이 실제 주소로 사용된다.
asm MOV AX, [BX] ; BX 레지스터가 가리키는 주소의 값을 AX에 저장
- 베이스-오프셋 주소 지정 (Base + Offset)
베이스 레지스터와 오프셋을 합산하여 최종 주소를 결정한다.
asm MOV AX, [BX + SI]
- 인덱스 주소 지정
배열과 같은 자료구조에 사용된다.
- 상대 주소 지정
프로그램 카운터(PC)를 기준으로 오프셋을 추가하여 주소를 계산한다. 주로 분기 명령에 사용된다.
이러한 다양한 방식은 효율적인 메모리 사용과 빠른 연산을 위해 설계되었다.
주소 공간과 가상 메모리[편집]
주소 공간(address space)은 특정 프로세스가 접근할 수 있는 모든 메모리 주소의 범위를 의미한다. 현대의 운영체제는 프로세스마다 고유의 가상 주소 공간을 할당하여 메모리를 보호하고 효율적으로 사용한다.
- 물리 주소 공간
실제 하드웨어 메모리 칩의 주소 범위입니다. 메모리 컨트롤러가 직접 접근하다.
- 가상 주소 공간
운영체제와 CPU의 메모리 관리 장치(MMU)가 물리 메모리를 가상화하여 사용하는 주소 공간이다. 가상 주소는 물리 주소와 다르며, 프로세스마다 독립적인 공간이 주어진다.
- 페이징과 세그먼트
가상 메모리를 관리하기 위한 기법으로, 페이징(paging)과 세그먼트(segmentation) 방식이 있다. 페이징은 메모리를 일정 크기의 블록(페이지)으로 나누어 관리하고, 세그먼트 방식은 의미 단위로 메모리를 분할한다.
메모리 주소의 종류[편집]
메모리 주소는 시스템 아키텍처와 메모리 관리 기법에 따라 여러 종류로 구분됩니다.
- 물리 주소 (Physical Address)
실제 메모리 칩에서 사용되는 주소이다.
- 가상 주소 (Virtual Address)
운영체제가 프로세스에게 제공하는 주소입니다. CPU의 MMU를 통해 물리 주소로 변환된다.
- 논리 주소 (Logical Address)
프로그램이 사용하는 주소로, 컴파일러나 링커에 의해 생성된다.
- 절대 주소 (Absolute Address)
프로그램 실행 시 사용하는 실제 주소이다.
- 상대 주소 (Relative Address)
기준점(예: 프로그램 카운터)으로부터의 거리로 표현되는 주소이다.
메모리 정렬과 주소[편집]
메모리 정렬(memory alignment)은 CPU가 효율적으로 메모리에 접근할 수 있도록 데이터를 일정한 경계(boundary)에 맞추어 저장하는 기법이다. 예를 들어, 4바이트 정수형 변수는 보통 4의 배수인 주소에 저장된다.
메모리 정렬이 잘못될 경우, 일부 아키텍처에서는 성능 저하나 오류가 발생할 수 있다.
주소와 포인터[편집]
C나 C++ 같은 저수준 언어에서는 포인터(pointer)를 통해 메모리 주소를 직접 다룰 수 있다. 포인터는 특정 타입의 데이터를 가리키는 메모리 주소를 저장하는 변수ㅣ다.
예:
c int x = 10; int *p = &x; // x의 주소를 p에 저장
포인터 연산을 통해 주소 이동, 메모리 접근 등을 직접 수행할 수 있으며, 이를 통해 동적 메모리 할당, 배열 처리, 함수 포인터 등 다양한 활용이 가능하다.
주소 변환 (주소 매핑)[편집]
CPU는 프로그램에서 사용하는 가상 주소를 실제 메모리 주소로 변환해야 한다. 이 과정은 메모리 관리 장치(MMU, Memory Management Unit)가 담당한다.
주소 변환 방식은 다음과 같다:
- 가상 주소 → 물리 주소
- 페이지 테이블을 통해 매핑
- 캐시 메모리를 활용하여 빠른 주소 변환
MMU는 CPU가 빠르게 주소를 변환할 수 있도록 TLB (Translation Lookaside Buffer) 라는 고속 캐시를 사용하기도 한다.
메모리 주소와 보안[편집]
메모리 주소와 보안은 밀접한 관계가 있다. 메모리 주소가 외부에 노출될 경우, 해커는 버퍼 오버플로우, 힙 스프레이, ROP(Return-Oriented Programming) 같은 공격을 통해 악의적인 코드를 실행할 수 있다.
이를 방지하기 위해 운영체제는 다음과 같은 기술을 사용한다:
- ASLR (Address Space Layout Randomization): 실행 시 메모리 주소를 무작위로 배치하여 공격자의 예측을 어렵게 한다.
- NX 비트 (No eXecute): 특정 메모리 영역을 실행 불가능하게 설정하여 악성 코드 실행을 차단한다.
- Stack Canary: 스택 버퍼 오버플로우를 탐지한다.
주소 버스와 주소 한계[편집]
CPU와 메모리 간의 통신을 위해 주소 버스(address bus)가 사용된다. 주소 버스의 폭이 커질수록 접근 가능한 메모리 공간이 넓어진다.
예:
- 16비트 주소 버스 → 64KB 주소 공간
- 32비트 주소 버스 → 4GB 주소 공간
- 64비트 주소 버스 → 이론상 16EB(엑사바이트) 주소 공간
현대 CPU는 64비트 아키텍처를 사용하지만, 실제 구현된 주소 폭은 더 작다. 예를 들어, 인텔의 x86-64 아키텍처에서는 48비트 물리 주소 공간을 사용한다.
프로그래밍 언어에서의 메모리 주소[편집]
고급 프로그래밍 언어는 메모리 주소를 추상화하여 프로그래머가 직접 다루지 않도록 한다. 하지만 C, C++, Rust 같은 시스템 프로그래밍 언어에서는 메모리 주소를 직접 관리해야 하며, 이는 강력하지만 위험할 수 있다.
Python, Java 같은 언어는 메모리 관리를 가비지 컬렉션(garbage collection)에 맡겨 메모리 주소를 숨긴다.
마이크로프로세서의 주소 공간[편집]
마이크로프로세서의 입장에서 메모리를 액세스할 때, 무한정의 주소값을 취급할 수 없다. 따라서 정해진 비트 수를 정해야 한다. 마이크로프로세서가 4비트로 시작하여 진화하면서 주소 공간도 확대되었다. 각각의 마이크로프로세서는 고유의 주소 공간을 갖는다. 이것이 주소 버스로 표현된다. 어느 경우는 복합적인 메모리 구조를 갖기도 한다. 일반적으로 8비트와 32비트 일반적 마이크로프로세서에서 주소표시 공간이 고정된다.
초기의 8비트 마이크로프로세서에서는 주로 16비트의 주소 공간을 갖는다. 인텔의 8080 계열에서 그리고 모토롤라의 68계열에서 16비트로 주소를 구별한다. 8080, 8085, Z-80, 6800, 6809, 6502 등의 8비트 마이크로프로세서는 16비트의 주소 공간을 갖는다.
8비트가 MCU로 진화 하면서 주소 공간이 다양해졌다. 8051의 경우 8비트 주소 공간과 16비트 공간을 분리해서 사용한다. 즉, 하나의 마이크로프로세서에서 2가지 주소 공간을 사용한다. 이렇게 2가지를 사용하려면 기계어가 2가지로 주소 공간을 취급할 수 있도록 분리해야 한다. MCU는 다양한 주소체계를 사용하므로 일반화 하기가 힘들고, 개발자가 확인해야 한다.
32비트로 진화하면 32비트의 주소 공간을 일반화된다. 거의 모든 32비트 CPU는 32비트 주소 공간을 갖는다. 인텔 x86(IA-32), 68020, ARM 등의 CPU가 32비트의 주소 공간을 갖는다.
많은 32비트에서 메모리의 관리를 위해 메모리 관리 장치(MMU)가 추가되어 운영 체제와 유기적 액세스가 이루어진다. 논리주소를 물리주소로의 변환은 메모리 자원을 관리하는 역할을 제공한다.
주소 지정 예시[편집]
간단한 예를 들어 보겠다.
c #include <stdio.h> int main() { int x = 42; printf("x의 값: %d\n", x); printf("x의 메모리 주소: %p\n", (void*)&x); return 0; }
위 코드에서 &x 는 변수 x 의 메모리 주소를 반환하며, %p 포맷을 사용하여 출력할 수 있다.
최신 트렌드: 64비트 주소 공간과 Beyond[편집]
현대 컴퓨터는 점점 더 많은 메모리를 요구한다. 64비트 아키텍처의 도입으로 엄청난 양의 메모리를 다룰 수 있게 되었으며, 데이터 센터, 고성능 컴퓨팅(HPC), 인공지능 학습 등에 활용되고 있다.
미래에는 메모리 계층 구조가 더 복잡해지고, 주소 지정 체계도 변화할 것이다. 예를 들어:
- NUMA (Non-Uniform Memory Access): CPU와 메모리 간 거리에 따라 접근 속도가 달라지는 구조.
- Persistent Memory: 재부팅 후에도 데이터가 유지되는 메모리 기술.
- 메모리 중심 컴퓨팅: CPU와 메모리 간의 경계가 흐려지는 차세대 컴퓨팅 패러다임.
참고자료[편집]
- 〈메모리 주소〉, 《위키백과》
같이 보기[편집]