4. 운영모드와 메모리 관리기법

x86과 x86-64프로세서에서 지원하는 메모리관리 기법은 크게 두가지이다.(세그먼테이션과 페이징)

  • 세그먼테이션
    • 우리가 전체역역을 원하는 크기로 분할하여 관리하는 것
  • 페이징
    • 지정 단위로 잘린 영역을 모아 원하는 크기를 만들어 관리하는 방식

메모리 관리기법을 사용하려면 관련 레지스터에 특정한 자료구조를 설정해야 한다.
세그먼테이션은
세그먼테이션 레지스터에 시작주소 혹은 Descriptor라고 불리는 자료구조의 위치를 설정해야한다.
페이징은
컨트롤 레지스터에 CR3레지스터에 Page directory라고 불리는 자료구조의 물리주소를 설정해야 사용할 수 있다.

리얼모드의 메모리 관리방식

  • 리얼모드는 최대 1MB까지 주소공간을 사용하며 세그먼테이션만 지원한다.
  • 리얼모드에서 세그먼트 크기는 64k로 고정
  • 세그먼트의 시작 어드레스는 세그먼트 레지스터에 직접 설정해야 한다.
  • 세그먼테이션에서 세그먼트의 시작 어드레스는 코드나 메모리에 접근할 때 기준 어드레스(Base address)로 사용됨

<리얼모드의 세그먼트 레지스터와 세그먼트, 몰리주소의 관계>


그림의 세그먼트레지스터 ES와 DS가 0x0200으로 되어있음. 16을 곱하면 0x2000이 된다.
그림의 밑에서 두번째 블럭(64K데이터)의 범위를 보면 0x2000 ~ 0x2fff인데 0x2fff-0x2000=0x0fff인데 이는 64k의 크기가 안된다.
범위가 0x2000 ~ 0x2fff이면 그림의 첫번째 블럭(64k 코드)부분의 영역과 겹치게 됨
그림이 이상한건지 내가 모르는게 있는 건지

  • 리얼모드에서는 세그먼테이션을 거쳐 나온 어드레스가 바로 물리주소가 됨
  • 리얼모드의 세그먼테이션은 세그먼트 레지스터의 값에 범용 레지스터의 값을 더하는 방식으로 동작함

<세그먼트 레지스터에 0x1000, 범용 레지스터에 0x1234가 설정되었을 때 물리주소를 계산하는 방법>

  • 세그먼트의 크기가 64KB인 이유는 바로 범용 레지스터의 크기 때문
  • 16비트 프로세서에는 32비트 레지스터가 없으며 범용레지스터는 모두 16비트 크기 따라서 16비트로 접근할 수 있는 범위가 0~0xffff이므로 세그먼트 크기도 64kb가 된 것

  • 보호모드 역시 같은 방식으로 세그먼트의 기준주소에 범용레지스터를 더해 계산함.
    다만, 페이징이 추가되어서 계산 결과는 논리주소로 바뀌었고, 논리주소는 페이징을 거쳐 물리주소로 바뀌게 됨.

보호모드의 메모리 관리 방식

  • 보호모드는 세그먼테이션과 페이징을 모두 지원함
  • 보호모드의 세그먼테이션은 디스크립터 자료구조의 위치(offset)를 설정하는 방식
  • 세그먼트 레지스터의 명칭도 세그먼트 셀렉터로 변경됨
  • 디스크립터는 메모리영역의 정보를 저장하는 자료구조로 여러 종류가 있음
  • 그중 세그먼트에 대한 정보를 나타내는 디스크립터를 세그먼트 디스크립터라고 부름

  • 세그먼트 디스크립터에는 세그먼트의 시작 어드레스와 크기, 권한, 타입등의 정보가 있음

<세그먼트 디스크립터의 구조>

  • 세그먼트 디스크립터에 포함된 특권레벨(DPL, Descriptor privilege level)은 해당 세그먼트에 접근하기 위한 최소한의 권한을 나타냄 숫자가 작을 수록 높은 권한이다.
  • 보호모드에서는 세그먼트 디스크립터의 위치를 가르킴
  • 세그먼트 디스크립터는 GDT(Global descriptor table)라고 불리는 곳에 모여있다.
  • GDT는 연속된 디스크립터의 집합
  • GDT 위치와 관련된 reg. 는 GDTR이다.
    • 16bit GDT size 필드와 32bit base addr필드로 구성된 자료구조의 물리주소를 넘겨 받는다.
    • processor는 이값을 가지고 있다가 segment selector를 통해 addr에 접근할 때마다 GDT의 위치를 찾는데 참조한다.

  • 선형주소와 물리주소가 1:1로 대응하도록 설정
  • 메모리구조는 최대한 간단하게 유지하는 편이 좋다

아래그림은 세그먼테이션과 페이징을 통해 논리주소->물리주소로 변환하는 과정

  • 3단계 페이징은 선형주소(논리주소)를 directory, table, offset 3부분으로 나누며 물리메모리를 4kb 페이지로 나누어 관리하는 방식


-> 나온 선형주소에서 table(물리적인 공간, 메인메모리에 위치)에 있는 entry(32bit 주소)로 접근해서 entry로 다음 table의 기준주소를 정함

  • 프로세서가 페이징처리 과정에서 table을 사용하려면 우리가 직접위치를 알려줘야함
  • CR3 control reg.는 페이지 디렉터리의 시작주소를 가르킨다.
  • 페이지 디렉터리 엔트리의 위치계산에 사용됨

  • 선형주소는 디렉터리 오프셋 10bit, table offset 10bit, page offset 12bit로 구분
  • 2^12 = 2^2 * 2^10 = 4k

  • page directory entry = 다음에 위치하는 page table의 start address
  • page table entry = 다음에 위치하는 page의 start address
    • 선형주소의 offset = 물리주소
  • 아래 그림 참고

IA-32e 메모리관리

IA-32e모드의 segmentation은 보호모드의 segmentation과 차이가 거의없음

  1. segemnt descriptor에 설정된 기준주소와 크기에 관계없이 모든 segment가 기준주소는 0, 크기는 64bit전체로 설정.
    따라서 기준주소가 segment를 구분하지 않는다.
  2. 두가지 서브모드를 지원하므로 code segment descriptor에 L필드가 추가로 있음.
    0이면 호환모드, 1이면 64bit모드.

IA-32e모드의 페이징은 64bit 주소공간이므로 PAE기능이 기본으로 활성화
변환단계도 4kb 페이지는 5단계, 2mb페이지는 4단계
그로인해 새롭게 추가된 table: page map level 4 (PML4) table, page directory pointer table(PDPT)
PAE기능이 뭔지 모르겠다.

'Project > OS' 카테고리의 다른 글

6. Bootloader 만들기  (0) 2019.07.11
5. 부팅과 부트로더  (0) 2019.07.11
3. 운영모드와 레지스터  (0) 2019.07.11
2. 운영모드  (0) 2019.07.11
1. ubuntu18.04.2 LTS개발환경 세팅  (0) 2019.07.11

3. 운영모드와 레지스터

os를 개발하는 관점에서 운영모드는 크게 16비트모드, 32비트모드, 64비트 모드 3가지로 나뉠 수 있음.

범용레지스터

  • 계산, 메모리 어드레스 지정, 임시저장 공간등의 목적으로 사용함
  • 범용레지스터의 수는 프로세서가 지원하는 운영모드에 따라 다름
  • 범용 레지스터의 수가 늘어나면 수행속도가 개선됨
  • 관련된 값을 레지스터에 모두 올려서 계산함으로서 메모리에 접근을 최대한 줄이는 것
  • 이와 비슷한 효과는 함수 호출에도 그대로 적용됨
  • 다수의 범용레지스터에 함수 파라미터를 넣어 넘겨줌으로서 스택영역의 메모리에 접근하는 시간과 스택을 정리하는 시간을 줄일 수 있음
    <x86-64프로세서의 범용레지스터와 용도>

  • 64비트 범용레지스터는 하위 32비트, 16비트, 8비트의 크기로 구분하여 접근할 수 있고, 레지스터에 접두사를 붙여 접근하는 크기를 표시함

<운용모드에 따른 범용레지스터의 크기와 이름>

  • 리얼모드에서 16비트 크기 이하의 레지스터만 접근 가능한 것으로 표시되어 있지만, 오퍼렌드 크기 접두사(Operand-Size Prefix, 0x66)를 사용하거나 어드레스 크기 접두사(Address-Size Prefix, 0x67)를 사용하면 32비트 레지스터도 접근할 수 있음
  • 운영모드에 따라 접두사를 결합하는 방법에는 일정한 규칙이 있으며 사용한 접두사에 따라 명령어가 처리하는 오퍼랜드나 어드레스의 크기가 달라짐

<운영모드와 접두사에 따른 오퍼랜드 및 어드레스의 크기>


-> 리얼모드에서
REX접두사:X,
operand-size prefix: N,
address-size prefix: N
일 때
유효한 operand 크기가 16bit,
유효한 address 크기가 16bit
이다.

여기서 한가지 의문점은 과연 접두사가 의미하는 것이 무엇이며
어떻게 사용하는지 이다.
원래 사이즈가 64bit 레지스터인데 접두사를 붙임으로서 확장, 축소 해서 사용하는 것인지
따로 각 접두사별 레지스터가 존재하는 것인지

  • 그림을 보면 IA-32e모드의 기본 오퍼랜드 크기가 32비트로 표시되어 있음
  • IA-32e 64bit모드는 64비트모드 이므로 오퍼랜드의 크기와 어드레스트의 크기가 모두 64비트인 것이 당연함
  • IA-32e모드의 기본 오퍼랜드의 크기는 32비트, 기본 어드레스의 크기는 64비트로 설계되어 있음
  • 기본 오퍼랜드의 크기가 32비트로 설계되어 있어서 64비트 어드레스를 표현할 수 없다.
  • 그래서 RIP상대 어드레스라는 새로운 어드레스 계산방식이 도입되었음
  • RIP상대 어드레스 레지스터는 현재 수행중인 명령의 어드레스를 가리키는 레지스터
  • RIP레지스터의 값과 32비트 오퍼랜드를 통해 64비트 주소공간을 나타낼 수 있다.
  • 하지만, 기본 오퍼랜드의 크기가 32비트이므로 RIP레지스터의 값에 상위 2G와 하위 2G범위 까지만 표현할 수 있는 단점이 있음
  • 64비트 오퍼랜드와 관계있는 REX접두사를 사용해 범위를 벗어나느 어드레스에 접근해야 함
  • REX접두사를 사용하면 오퍼랜드의 크기가 64비트가 되고 따라서 64비트 어드레스를 모두 표현할 수 있음

여기서 REX접두사가 뭘까?

<RIP상대 어드레스와 메모리 영역>


->RIP는 현재 수행중인 명령의 어드레스를 가리키는 reg.
RIP가 옮겨다니며 -2G ~ +2G의 범위 만큼 RIP상대
어드레스에 접근이 가능한 것

세그먼트 레지스터

  • 16비트 레지스터로 어드레스 영역을 다양한 크기로 구분함

  • 리얼모드에서는 단순히 고정된 크기의 어드레스 영역을 지정함

  • 보호모드와 IA-32e모드에서는 접근권한, 세그먼트의 시작 어드레스와 크기등을 지정하는데 사용되기도 함
    <x86-64프로세서의 세그먼트 레지스터>

  • 세그먼트 레지스터의 역할은 주소 공간을 목적에 따라 구분한는 것이며, 주소공간을 구분하는 방법은 메모리 관리기법과 깊은 관계가 있음.

  • 메모리관리 기법에는 크게 세그먼테이션과 페이징 두가지가 있음. 이중 세그먼트레지스터를 통해 주소공간을 구분하는 방식이 세그먼테이션이다.*

컨트롤레지스터

  • 운영모드를 변경하고, 현재 운영중인 모드의 특정기능을 제어하는 레지스터
  • x86프로세서에는 CR0 ~ CR4의 5개의 컨트롤 레지스터가 존재
  • x86-64프로세서에는 CR8이 추가되어 총 6개의 컨트롤 레지스터가 있다.

<x86-64프로세서의 컨트롤 레지스터>

  • 컨트롤 레지스터는 리얼모드와 보호모드일 때 32비트 크기이다.
  • IA-32e모드에서는 64비트로 확장되지만 일부 제약 사항이 있다.
    • CR0와 CR4, CR8레지스터에서는 64비트 영역을 모두 사용할 수 있다.
    • CR2레지스터의 경우는 64비트 영역을 모두 사용할 수 있다.
    • CR3레지스터는 비트40부터 51까지 모두 0으로 설정해야 한다.

<컨트롤 레지스터의 구조>

  • 각필드는 저마다 특정기능을 활성화/비활성화 하며, 현재 운영모드에 따라 필수 필드와 옵션필드가 달라진다.
  • 컨트롤 레지스터의 특정기능은 해당비트를 1로 설정해도 충분하지만, 특정기능은 1로 설정하기 전에 프로세서가 사용할 자료구조를 미리 준비해야한다.

'Project > OS' 카테고리의 다른 글

6. Bootloader 만들기  (0) 2019.07.11
5. 부팅과 부트로더  (0) 2019.07.11
4. 운영모드와 메모리 관리기법  (0) 2019.07.11
2. 운영모드  (0) 2019.07.11
1. ubuntu18.04.2 LTS개발환경 세팅  (0) 2019.07.11

2. 운영모드

주변에서 많이 사용하는 intel 64bit 호환프로세서(x86-64 프로세서)에는 크게 5가지 운영모드가 있음.

리얼모드

  • 전원이 켜지거나 리셋되면 리얼모드로 진입한다.
  • 프로세서의 초기상태로서 16bit 모드로 동작(리얼모드는 과거의 16비트 프로세서와 동일하게 동작)
  • BIOS의 여러기능을 사용할 수 있음
  • 최대 1MB(2^20)의 주소공간을 지원
  • 디바이스 드라이버를 제작하지 않아도 됨
  • 리얼모드에서 하는 작업은 os이미지를 디스크에서 메모리로 복사하여 보호모드로 변경하는 것
  • 대부분 작업을 어셈블리어로 처리해야한다.

보호모드

  • 32bit 모드로 동작하며 세그먼트, 페이징, 보호, 멀티태스킹등의 기능을 제공하는 모드
  • 4GB(2^32)의 주소공간을 지원
  • IA-32e 모드로 전환하려면 반드시 거쳐야 하는 모드
  • 32bit윈도우나 리눅스 os가 동작하는 기본모드
  • os의 필수기능으로 자리잡은 보호, 멀티태스킹, 세그멘테이션, 페이징등의 기능을 하드웨어적으로 지원한다.

IA-32e 모드

  • 32bit 호환모드와 64bit 모드 두가지 서브모드로 구성(이중 32bit 호환모드는 보호모드와 같은 기능을 수행함)
  • 16EB(2^64)의 주소공간을 지원하는 모드
  • 대부분의 자료구조는 보호모드와 같고, 크기만 2배로 확장되고 일부 필드의 의미가 변하는 정도 이므로 보호모드와 큰차이는 없음
  • 프로세서가 32bit 호환모드에 있는 것 처럼 동작하므로 32bit코드를 그대로 실행할 수 있음.
  • 이는 간단히 서브모드만 변경함으로서 보호모드 코드를 실행할 수 있다는 뜻

시스템 관리 모드

  • 전원 관리나 하드웨어 제어같은 특수기능을 제공하는 모드

가상 8086 모드

  • 보호모드 내부에서 가상의 환경을 설정하여 리얼모드처럼 동작하는 모드

이중 64bit os가 필수적으로 갖추어야 할 운영모드는
[리얼모드], [보호모드], [IA-32e 64bit 모드] 3가지 이다.

<운영모드 사이의 관계>

'Project > OS' 카테고리의 다른 글

6. Bootloader 만들기  (0) 2019.07.11
5. 부팅과 부트로더  (0) 2019.07.11
4. 운영모드와 메모리 관리기법  (0) 2019.07.11
3. 운영모드와 레지스터  (0) 2019.07.11
1. ubuntu18.04.2 LTS개발환경 세팅  (0) 2019.07.11

+ Recent posts