Part5. Intel Architecture에 대한 소개

원문 :  http://kkamagui.springnote.com/pages/339549

 

들어가기 전에...


0.시작하면서...

 앞서 인터럽트와 어셈블리어에 대해서 설명을 했다. 이제 프레임워크의 기반 환경인  Intel CPU Architecture에 대해서 알아보자.

 

1.Intel Architecture 다이어그램

 아래 그림은 System Programming 관점에서 본 i386 Architecture에 대한 그림이다. (참고로 여기 나오는 모든 그림은 다 Intel Architecture Manual에서 찾을 수 있다).
 Intel3.png

 

<Intel System Architecture>

 

 

 굉장히 복잡하게 그려져있는데, 프레임워크를 이해하기위해 필요한 부분은 General Register, Segment Register, Descriptor 정도이다.

 

2.레지스터(Register)와 16/32bit 모드(Mode)

 i386 Architecture는 16bit와 32bit 두가지 모드를 가지고 있는데, 16bit모드 일때와 32bit 모드일때 Segment Register의 역할이 다르고 사용가능한 General Register의 크기가 다르다는 차이가 있다. 16bit 모드에 대해서는 궁금한 사람은 Intel Architecture 메뉴얼을 참조 하도록하고 여기서는 32bit 모드에 중점을 두겠다.

 

2.1 레지스터(Register) 종류

 32bit 모드보호 모드(Protected Mode)라고 하는데, 권한에 따른 메모리 보호와 접근 범위 설정이 가능하기 때문이다. 32bit 모드에서 레지스터는 아래와 같이 구성된다.

Intel4.png

<32bit Mode Register>

 

 위의 각 레지스터 역할은 아래와 같다. 

  • General Register : 연산이나 비교, 저장 용으로 사용되는 레지스터
  • Segment Register : Descriptor를 지시하는 역할을 하는 레지스터
  • EFLAGS Register : 비교연산이나 산술연산의 결과의 Overflow, Underflow 같은 연산에 대한 결과 값과 인터럽터 가능/불가와 같은 전체적인 상태값을 저장하는 레지스터
  • EIP Register : 수행중인 명령의 위치를 가리키는 레지스터(Instruction Pointer)

 

 Segment Register는 디스크립터(Descriptor)를 지시하는 역할을 한다고 했는데, 디스크립터에 대해서는 다음에 상세하게 알아보도록 하자.

 

2.2 세그먼트 셀렉터(Segment Selector)

 32bit Mode에서 Segment Register의 역할은 아주 단순하다. 바로 디스크립터를 지시하고 현재 Level(Ring 0, Ring1, Ring2, Ring 3)을 표시하는 역할이다.

 아래는 Intel Architecture에서 Segment Register의 비트별 용도를 나타낸 것이다.

 Intel1.PNG

<Segment Selector>

 

 Bit 3~15까지가 실제 디스크립터의 인덱스를 의미한다. 그렇다면 아래의 3bit의 용도는 무엇일까? 3bit의 용도는 아래와 같다.

  • TI bit : 디스크립터가 전역 디스크립터 테이블(Global Descriptor Table)에 있는지 지역 디스크립터 테이블(Local Descriptor Table)에 있는지를 의미
  • RPL bit : 해당 디스크립터에 접근하기위한 권한 레벨. 만약 RPL이 디스크립터에 설정된 DPL보다 값이 크면(낮은 레벨이면) 디스크립터에 접근 불가

 디스크립터의 인덱스 설정과 동시에 권한을 설정해 주는 필드로 체워져 있음을 알 수 있다. 권한에 따른 보호는 CPL과 RPL 그리고 DPL이 서로 엮여져 있는데 이에 대한 자세한 내용은 참고. Intel i386 CPU의 보호(Protection) 방식을 참고하자.

 

2.3 디스크립터(Descriptor)

 디스크립터(Descriptor)가 무엇인고 하니, 메모리 범위를 지정하고 해당 메모리의 속성을 지정하는 기술자(Descriptor)이다. 언듯 이해가 잘 안갈텐데, 이것을 이해하려면 OS의 메모리 관리 기법중에 세그먼테이션(Segmentation)에 대한 내용을 알고 있어야 한다. 세부적인 내용은 OS책을 보도록 하고 간단히 개요만 설명하겠다.

 

 Intel5.png

<Segment Register와 Segment의 관계>

 

 

 위의 그림이 Segment Register와 디스크립터의 관계를 표시한 것이다. 각 Segment Register는 한개의 디스크립터를 지시할 수 있고,  디스크립터는 코드영역인지, 데이터 영역인지, 스택영역인지에 대한 속성과 범위(시작과 끝)를 가지는 세그먼트(Segment)의 내용을 담고 있다. 즉 OS의 각 영역은 여러개의 조각(Segment)로 구분될 수 있으며, 각각의 세그먼트에 대한 구체적인 내용(속성, 시작, 끝 등등)을 가지고 있는 것이 디스크립터이다.

 하나의 디스크립터는 여러개의 Segment Register에 의해 선택될 수 있고, 극단적인 상황에서 모든 Segment Register가 하나의 디스크립터를 지시할 수 있다.(단 해당 디스크립터의 속성은 그에 합당하는 속성(코드/데이터 속성 등등)을 모두 가지고 있어야 한다.)

 Intel2.PNG

<Descriptor 구조체>

 

 디스크립터는 위에서 보는 것과 같이 시작 및 크기, 속성, 특권 레벨(DPL)로 구성되어있다. 디스크립터에 대한 자세한 내용은 Intel Architecture Manual 및 참고. Intel i386 CPU의 보호(Protection) 방식 문서를 참고하도록 하자.

 

 그럼 Segment와 General Register와 Address 간의 관계는 어떻게 되는걸까? 암묵적으로 Segment Register가 사용되는 부분은 아래와 같다.

1. CS : 코드 수행 시 암묵적으로 사용
2. DS : 데이터 접근 시 암묵적으로 사용
3. SS : 스택 접근 시 암묵적으로 사용

 

 그렇다면 절대 주소(Absolute Address)의 계산은 어떻게 되는걸까?

1. 실제 코드가 수행되는 메모리 절대 주소 : CS가 가리키는 디스크립터의 Base Address + EIP
2. 데이터 접근이 수행되는 메모리 절대 주소 : DS가 가리키는 디스크립터의 Base Address + Memory Address
3. 스택 연산이 수행되는 메모리 절대 주소 : SS가 가리키는 디스크립터의 Base Address + ESP, EBP

 위와 같이 된다. 우리가 접근하는 위치는 디스크립터의 Base Address를 시작으로 하는 위치가 되기 때문에 이를 잘 생각해야 한다. 커널을 빌드하고 이를 실행했을 때 영향을 미치기 때문이다. 프레임워크에서는 단순하게 하기위해 Segment를 크게 2개(코드/데이터)로 구분하고 Base Address를 0, 크기를 4GByte로 설정했기 때문에 커널 코드에서 사용하는 위치는 절대 주소라고 보면 된다.

 

 

2.4 프로세스 모드(Processor Mode)

 자 그럼 여기서 잠깐만 Intel Architecture가 가지는 여러 모드(Mode)에 대해서 집고 넘어가자. 지금 16bit와 32bit 모드만 설명했는데, 2개의 모드가 전부일까?

 그렇지 않다. Intel Architecture Volume3을 참고하면 알겠지만 여러가지 모드가 존재한다.

Intel_Mode.PNG

<Intel CPU Mode 전환>

 

 위의 모드에 대해서 전부 설명하려면 책 한권으로도 부족하므로 궁금한 사람은 Intel Architecture Manual을 참고하도록 하고 간단히 설명만 하겠다.

  • Real-Address Mode : 16bit 모드
  • Protected Mode : 32bit 모드. 프레임워크가 사용하는 모드
  • Virtual-8086 Mode : 32bit 모드에서 16bit 모드를 실행하기위한 에뮬레이션 환경.
  • IA-32e Mode : 64bit 모드 또한 32bit 호환 모드

 우리가 주로 사용하는 모드는 Protected Mode 이고 처음 시스템이 부팅되었을 때 모드는 Real-Address Mode라는 것만 알아두자.

 

 

3.스택(Stack)

 마지막으로 프로그램 제작이든 커널 제작이든 꼭 필요한 스택에 대해서 알아보자.

Intel6.png

<Intel CPU의 Stack 구조>

 

 

 위의 그림에서도 나와있지만 i386의 스택은 높은 주소(0xFFFFFFFF 쪽)를 Base로 하고 낮은주소(0x0000 쪽)로 자라게 되어있다. 그렇기 때문에 앞서 본 호출 규약(Calling Convention)에서도 Parameter 접근시 ebp + 0x08과 같은 숫자를 더하는 방식으로 접근한 것이다.
 커널 프로그래밍을 하면 스택이 어느 방향으로 자라고 Top이 항상 어디에 위치하는지 확실하게 알고 있어야 한다. C와 어셈블리어 간의 함수 호출이라던지, 하드웨어적인 도움을 받지 않고 소프트웨어적으로 하는 태스트 스위칭이라던지 하는 부분은 모두 스택을 사용하기 때문에 스택을 제대로 이해하지 못하면 앞으로 나갈 수 없다.

 스택을 제대로 이해하고 있으면 불가능하게 보이는 일도 가능하게 만들 수 있다(32bit 모드에서 16bit BIOS 함수를 호출하는 것과 같은 일들...). 스택의 개념을 머리속에 항상 새겨놓도록 하자.

 

4.마치면서...

 Intel Architecture에 대해서 간단하게 알아보았다. 다음부터는 프레임워크에 대한 설명을 할 것이므로 지금까지 한 내용을 참고하면서 보면 많은 도움이 될 것이다.

 

 

 

 

이 글은 스프링노트에서 작성되었습니다.

이 글은 스프링노트에서 작성되었습니다.

+ Recent posts