검색
회원가입로그인
AI와 함께 공부하기 : 컴퓨터 구조

MIPS 메모리 접근 방식 정리

MIPS의 메모리 접근

목차

  1. MIPS 메모리의 기본 특성
     1.1. 바이트 주소 지정 (Byte-Addressable Memory)
     1.2. 워드(Word)의 정의와 크기
     1.3. 데이터 정렬 제약 (Alignment Restriction)
     1.4. 엔디안(Endianness)

  2. 메모리 접근 명령어 (Data Transfer Instructions)
     2.1. LOAD 명령어 (메모리 → 레지스터)
     2.2. STORE 명령어 (레지스터 → 메모리)

  3. 메모리 접근 주소 지정 방식 (Addressing Mode)

  4. 고급 활용 및 주의사항
     4.1. Large Constant (큰 상수 로딩)
     4.2. 가상 레지스터 $gp (Global Pointer)
     4.3. 스택(Stack) 접근

  5. 파이프라인 관점에서의 메모리 접근

MIPS는 전형적인 로드/스토어(Load/Store) 아키텍처를 따릅니다. 이는 CPU가 메모리에 직접 접근하여 연산을 수행하는 것을 허용하지 않고, 모든 데이터 연산이 레지스터 내에서만 이루어져야 한다는 근본적인 제약을 의미합니다. 메모리와 레지스터 간의 데이터 이동은 오직 LOAD (메모리 -> 레지스터)와 STORE (레지스터 -> 메모리)라는 두 가지 유형의 명령어만을 통해 이루어집니다.

1. MIPS 메모리의 기본 특성

1.1. 바이트 주소 지정 (Byte-Addressable Memory)

  • 최소 주소 단위: MIPS 메모리는 1바이트(8비트) 단위로 주소가 지정됩니다. 즉, 메모리의 각 바이트는 고유한 32비트 주소를 가집니다.

  • 이는 메모리의 특정 바이트를 참조하거나, 문자(character)와 같이 작은 단위의 데이터를 저장하고 읽을 때 필수적입니다.

1.2. 워드(Word)의 정의와 크기

  • MIPS에서 **워드(Word)**는 32비트(4바이트)를 의미합니다. MIPS 프로세서의 레지스터 크기와 대부분의 정수 연산 단위가 32비트이기 때문입니다.

  • CPU는 한 번에 32비트 워드를 처리하는 데 최적화되어 있습니다.

1.3. 데이터 정렬 제약 (Alignment Restriction)

  • MIPS의 가장 중요한 메모리 접근 규칙 중 하나는 **데이터 정렬(Alignment)**입니다.

    • 워드(4바이트) 접근: lw (load word), sw (store word)와 같이 4바이트 워드 단위로 메모리에 접근할 때는 해당 메모리 주소가 반드시 4의 배수여야 합니다.

      • 예: 0x0000, 0x0004, 0x0008, ...

    • 하프워드(2바이트) 접근: lh (load halfword), sh (store halfword)와 같이 2바이트 하프워드 단위로 메모리에 접근할 때는 해당 메모리 주소가 반드시 2의 배수여야 합니다.

    • 바이트(1바이트) 접근: lb (load byte), sb (store byte)와 같이 1바이트 단위로 메모리에 접근할 때는 주소 정렬 제약이 없습니다 (모든 바이트 주소는 1의 배수).

  • 정렬의 중요성 (Why Alignment? - Ultrathinking Perspective):

    • 하드웨어 단순화 및 효율성: 메모리 버스(Bus)는 보통 32비트(4바이트) 또는 64비트(8바이트) 단위로 데이터를 전송합니다. 워드 정렬이 강제되면, CPU는 메모리 컨트롤러에게 특정 4바이트 블록의 시작 주소를 한 번만 알려주면 됩니다. 메모리 컨트롤러는 해당 주소부터 4바이트를 한 번의 연산으로 가져올 수 있습니다.

    • 성능 최적화: 만약 워드가 정렬되지 않은 주소(예: 0x0001)에 있다면, 4바이트 워드를 읽기 위해 두 번의 메모리 접근이 필요할 수 있습니다 (0x0000~0x0003 블록에서 3바이트, 0x0004~0x0007 블록에서 1바이트). 이 두 번의 접근은 성능을 크게 저하시킵니다. 정렬은 이를 방지하고 예측 가능한 단일 사이클 메모리 접근을 가능하게 합니다.

    • 예외 처리: MIPS 하드웨어는 정렬되지 않은 접근을 감지하면 Alignment Error와 같은 예외(exception)를 발생시킵니다. 이는 프로그래머에게 잘못된 메모리 접근을 알리고 시스템 안정성을 유지하는 데 도움이 됩니다. (일부 시스템에서는 예외를 발생시키지 않고 소프트웨어적으로 처리하기도 하지만, 성능 저하가 큽니다.)

1.4. 엔디안(Endianness)

  • MIPS 아키텍처는 대부분 빅 엔디안(Big-Endian) 방식을 사용합니다. 빅 엔디안은 워드 내에서 가장 중요한 바이트(Most Significant Byte)를 가장 낮은 메모리 주소에 저장하는 방식입니다.

  • 예를 들어, 32비트 값 0x12345678이 주소 0x1000에 저장될 때:

    • 0x1000: 0x12

    • 0x1001: 0x34

    • 0x1002: 0x56

    • 0x1003: 0x78

  • 일부 MIPS 프로세서는 설정에 따라 리틀 엔디안(Little-Endian)을 지원하기도 하지만, 기본은 빅 엔디안입니다.

2. 메모리 접근 명령어 (Data Transfer Instructions)

MIPS의 모든 메모리 접근은 I-Type 명령어 형식을 사용합니다. 이 명령어들은 다음과 같은 공통 구조를 가집니다:

opcode rs rt offset

  • opcode: 명령어의 종류 (예: lw, sw).

  • rs: 베이스 레지스터(Base Register). 메모리 주소 계산의 기준이 되는 주소 값을 담고 있는 레지스터.

  • rt: 목적지/소스 레지스터(Target/Source Register). LOAD 명령어의 경우 메모리에서 읽어온 데이터가 저장될 레지스터, STORE 명령어의 경우 메모리에 쓸 데이터가 담긴 레지스터.

  • offset: 16비트 부호 확장(Signed Extension)된 상수 값. 베이스 레지스터 값에 더해져 최종 메모리 주소를 계산하는 데 사용되는 변위(displacement).

2.1. LOAD 명령어 (메모리 -> 레지스터)

메모리에 있는 데이터를 레지스터로 가져오는 명령어들입니다.

  • lw rt, offset(rs): Load Word

    • rt = Memory[rs + offset]

    • rs 레지스터 값과 offset (부호 확장된 16비트)을 더하여 메모리 주소를 계산합니다.

    • 계산된 주소에서 4바이트(1워드)를 읽어와 rt 레지스터에 저장합니다.

    • 정렬 제약: rs + offset 결과 주소는 반드시 4의 배수여야 합니다.

  • lh rt, offset(rs): Load Halfword

    • rt = SignExtend(Memory[rs + offset])

    • 계산된 주소에서 2바이트(1하프워드)를 읽어와 rt 레지스터의 하위 16비트에 저장하고, 상위 16비트는 부호 확장으로 채웁니다.

    • 정렬 제약: rs + offset 결과 주소는 반드시 2의 배수여야 합니다.

  • lhu rt, offset(rs): Load Halfword Unsigned

    • rt = ZeroExtend(Memory[rs + offset])

    • lh와 동일하지만, 상위 16비트를 제로 확장으로 채웁니다 (음수 값 처리 없음).

    • 정렬 제약: rs + offset 결과 주소는 반드시 2의 배수여야 합니다.

  • lb rt, offset(rs): Load Byte

    • rt = SignExtend(Memory[rs + offset])

    • 계산된 주소에서 1바이트를 읽어와 rt 레지스터의 하위 8비트에 저장하고, 상위 24비트는 부호 확장으로 채웁니다.

    • 정렬 제약: 없음 (모든 바이트 주소 유효).

  • lbu rt, offset(rs): Load Byte Unsigned

    • rt = ZeroExtend(Memory[rs + offset])

    • lb와 동일하지만, 상위 24비트를 제로 확장으로 채웁니다.

    • 정렬 제약: 없음.

2.2. STORE 명령어 (레지스터 -> 메모리)

레지스터에 있는 데이터를 메모리로 저장하는 명령어들입니다.

  • sw rt, offset(rs): Store Word

    • Memory[rs + offset] = rt

    • rs 레지스터 값과 offset을 더하여 메모리 주소를 계산합니다.

    • rt 레지스터의 4바이트 값을 계산된 주소에 저장합니다.

    • 정렬 제약: rs + offset 결과 주소는 반드시 4의 배수여야 합니다.

  • sh rt, offset(rs): Store Halfword

    • Memory[rs + offset] = rt[15:0]

    • rt 레지스터의 하위 2바이트(16비트)를 계산된 주소에 저장합니다.

    • 정렬 제약: rs + offset 결과 주소는 반드시 2의 배수여야 합니다.

  • sb rt, offset(rs): Store Byte

    • Memory[rs + offset] = rt[7:0]

    • rt 레지스터의 하위 1바이트(8비트)를 계산된 주소에 저장합니다.

    • 정렬 제약: 없음.

3. 메모리 접근 주소 지정 방식 (Addressing Mode)

MIPS의 로드/스토어 명령어는 기본적인 베이스/변위(Base/Displacement) 주소 지정 방식을 사용합니다.

  • Effective_Address=Base_Register_Value+SignExt(Offset)

  • Base Register: 프로그램의 기준 주소(예: 배열의 시작 주소, 스택 포인터)를 포함하는 rs 레지스터입니다.

  • Offset: 기준 주소로부터의 상대적인 거리(변위)를 나타내는 16비트 상수입니다. 16비트이므로 ±32KB 범위의 주소에 접근할 수 있습니다.

  • 장점:

    • 유연성: 배열 요소(A[i])나 구조체 멤버(struct.member)에 접근할 때 베이스 레지스터에 시작 주소를 담고, 오프셋으로 원하는 요소의 위치를 지정할 수 있어 매우 효율적입니다.

    • 코드 재배치 가능성(Relocatability): 프로그램의 절대 주소에 의존하지 않고, 레지스터에 담긴 베이스 주소를 기준으로 상대적인 오프셋을 사용하므로, 코드가 메모리 어디에 로드되든 올바르게 작동할 수 있습니다.

4. 고급 활용 및 주의사항

4.1. Large Constant (큰 상수 로딩)

  • lui rt, immediate (Load Upper Immediate): 16비트 immediate 값을 rt 레지스터의 상위 16비트에 로드하고 하위 16비트를 0으로 채웁니다.

  • 큰 32비트 상수를 레지스터에 로드하거나, 16비트 offset으로 접근할 수 없는 넓은 메모리 주소를 지정해야 할 때 luiori 또는 addi를 조합하여 사용합니다.

    • 예: 32비트 주소 0xABCD1234에 접근하려면:

      코드 스니펫

      lui $t0, 0xABCD  # $t0 = 0xABCD0000
      ori $t0, $t0, 0x1234 # $t0 = 0xABCD1234
      lw $t1, 0($t0) # $t1 = Memory[0xABCD1234]
      

4.2. 가상 레지스터 $gp (Global Pointer)

  • MIPS는 프로그램의 전역 데이터 영역에 효율적으로 접근하기 위해 $gp (글로벌 포인터)라는 특정 레지스터를 사용합니다.

  • $gp는 전역 데이터 영역의 중간 지점을 가리키도록 설정되며, offset을 이용하면 $gp \pm 32KB 범위 내의 전역 변수에 단일 Load/Store 명령어로 접근할 수 있습니다. 이는 컴파일러가 전역 변수 접근 코드를 최적화하는 데 사용됩니다.

4.3. 스택(Stack) 접근

  • 스택은 주로 지역 변수, 함수 인자 전달, 복귀 주소 저장 등에 사용됩니다.

  • $sp (Stack Pointer) 레지스터는 스택의 현재 최상단(Top)을 가리킵니다.

  • 스택 접근은 lw 또는 sw 명령어를 offset($sp) 형태로 사용하여 이루어집니다. offset은 스택 포인터($sp)를 기준으로 특정 위치에 저장된 데이터에 접근하는 데 사용됩니다.

5. 파이프라인 관점에서의 메모리 접근

MIPS의 Load/Store 아키텍처는 5단계 파이프라인에서 MEM(Memory Access) 단계를 매우 단순하고 독립적으로 만들었습니다.

  • IF (Instruction Fetch): 명령어 메모리에서 명령어를 가져옴. (메모리 읽기)

  • ID (Instruction Decode/Register Fetch): 명령어 해독, 레지스터 값 읽기.

  • EX (Execute): ALU 연산 수행 (Load/Store 명령의 경우 메모리 주소 계산).

  • MEM (Memory Access): 계산된 주소를 사용하여 데이터 메모리에서 읽거나 씀. Load/Store 명령어만 이 단계에서 데이터 메모리에 실제로 접근합니다. 다른 연산 명령어는 이 단계를 그냥 통과합니다.

  • WB (Write Back): 연산 결과 또는 로드된 데이터를 레지스터 파일에 씀.

이러한 분리는 파이프라인의 **구조적 해저드(Structural Hazard)**를 줄이고, 각 단계의 실행 시간을 균등하게 만들어 파이프라인 효율을 극대화하는 데 기여합니다. (예: 명령어 Fetch가 명령어 메모리를 사용하고, 데이터 Load/Store가 데이터 메모리를 사용하도록 메모리를 분리하는 하버드 아키텍처 방식)


공유하기
카카오로 공유하기
페이스북 공유하기
트위터로 공유하기
url 복사하기