[[TableOfContents]] = Inside CPU = ''' CAUTION :: 검증하기 않고 쓰인 부분이 있습니다. 수정해 주시면 감사하겠습니다 ''' [[BR]] = DOC 버전 = VER 0.2 = 목적 = CPU 에 대해 보다 깊이 이해하고 싶은 마음에 문서를 작성하게 되었습니다.[[BR]] * == 부팅에 관해 == === 과정 === 1. 처음 컴퓨터를 키면 참조하는 메모리가 F000:FFF0 이라는 부분이다. 여기서 CPU는 ROM-BIOS를 적재하게 되고 제어권이 ROM-BIOS의 프로그램으로 넘어가게 된다. 2. 이후 ROM-BIOS는 일련의 CHECK 프로그램을 실행 시킨다. 흔히 보는 하드웨어 CHECK와 메모리 CHECK가 여기에 속한다. 3. 모든 CHECK가 끝나면 ROM-BIOS는 컴퓨터의 부팅 가능한 드라이브를 찾는다. 이 순위는 CMOS 셋업에서 바꿔 줄 수 있다. :: 참고 여기서 부팅 가능한 드라이브는 sector 0 번지에 섹터에 마지막 코드가 AA55h인 드라이브를 말한다. 4. 부팅 가능한 드라이브의 0번 섹터를 읽어 들여 0000:7C00 에 적재 시킨다. 그리고 CS를 0000:7C00 으로 옮긴다. 5. 그럼 로더 프로그램이 적재 된 상태이다. 이것으로 부팅은 끝이다. 이후 부터는 로더가 작업을 실행한다. === 참고 사항 === 위에 로더는 1섹터(512KB) 밖이 되지 않는다. 이는 작은 프로그램 밖이 실행 할 수 없고 메모리의 위치가 0000:7C00으로 불안한 위치이다. 대부분의 커널의 경우 이 메모리 블럭을 넘어서는 크기를 갖게 되므로 바로 커널을 로딩할 경우 로더의 메모리를 잡아 먹게 된다. 그래서 보통 Kernel로더는 자신을 보다 먼 곳의 안전한 곳으로 이동시키고 커널을 로딩하게 된다. 위와 같은 경우는 플로피에 해당하는 경우이다. 하드드라이브처럼 파티션이 여러개인 경우 MBR 마스터 부트 레코드가 존재하며 멀티 부팅을 위핸 lilo/grub이 올려져 부팅이미지가 있는 파티션을 찾아준다. 플로피와 같은 경우 플로피에 대한 해당 정보를 적어줘야 나중에 플로피 디스크를 DOS에서 읽을 수 있다. 해당 정보는 0번 섹터에 다음과 같은 layer를 적어준다. || offset || field description || || 00h || 점프 코드(머쉰코드) || || 03h || OEM identification || || 0Bh || Bytes per sector || || 0Dh || Sectors per cluster || || 0Eh || Nums of reserved sectors || || 10h || Nums of FATs|| || 1Eh ~ 1FDh || 실제 로더 코드 || 음...여기까지만..귀찮아서 못 적겠다.. 보통 플로피의 0번 섹터를 write하기 위해 rawrite.exe란 프로그램을 쓴다. 플로피의 데이타를 얻기 위해 BIOS의 인터럽트루틴을 사용한다. 이를 위한 인터럽트는 INT 13h가 된다. == 실모드에 관해 == 실모드는 컴퓨터를 키면 항상 실모드가 된다. 이는 하위 CPU에 대한 호환 정책으로 만들어진 것이며 열라 빠르게 움직이는 (펜티엄클럭) 8086이라고 보면 적당할 것이다. 또한 실모드에서는 메모리 어드레싱 방법이 8086과 동일한 20bit의 어드레스 비트를 가지고 있으며 즉 1MB 의 접근만을 허용한다. 또한 640KB의 base로 접근하고 384KB는 extends로 접근해야 하며 위의 메모리에는 ROM-BIOS와 Video Memory가 있다. 1MB를 접근하기 위해서는 16bit의 세그먼트와 16bit의 오프셋으로 구성된 물리적 접근이 있다. 0000h:0000h가 그 예이며 이를 4bit 어긋나게 더해 20bit를 만들어 접근하게 된다. == 보호모드에 관해 == 보호모드란 80286부터 적용된 하드웨어적 지원이다. 이는 다른 CPU에도(다른 이름으로) 존재하며 운영체제에게 안전한 태스크 관리와 보다 빠른 Context Switching 을 적용할 수 있다. 이를 위해 몇몇의 assemble 코드가 추가 되었으며 80386 부터는 코드가 확장되어 보다 큰 메모리를 어드레스 할 수 있게 되었다. [[BR]] ''' 왜 보호 모드가 필요한가 '''[[BR]] 보호모드가 없을 경우 커널은 자신을 지키기 위한 하드웨어적 방법을 잃게 된다. 만약 일반 유저 어플리케이션에서 아무런 제약없이 커널의 메모리 블럭에 접근할 수 있다면 ... 으..생각만해도 끔찍하다. {{{~cpp 실례:: 어셈을 하다보면 이유없이 이런 코드를 쓰는 경우가 있다. MOV AX,FFFFH MOV DS,AX 으! 그냥 MOV DS,FFFFFH 하면 되지 왜 AX에 넣는 것이야. 지금 사용 FFFFFH란 메모리가 지금 프로세스가 참조할 수 있나 세그먼트의 정당성을 알기 위해서 이다....보호 할 수 있겠지..그럼.. }}} 이를 위해 각각의 어드레스 접근에 privilege level을 두었고 이를 각각의 Application에 적용시켰다. 보호모드의 경우 멀티태스킹을 지원하기 위한 방법이다. 이는 지속적이고 반복적으로 일어나는 Context Switching 을 하드웨어적인 방법으로 만들어 소프트웨어적인 방법보다 빠른 Context Switching을 통해 하드웨어의 효율성을 높였다. 보호모드를 위한 레지스터와 방법들.. * Descriptor 디스크립터는 세그먼트에 접근을 위한 정보를 담고 있다. BASE,G,X,0,?,LIMITE,P,DPL,1,TYPE -> SEGMENT DESCRIPTOR FILED EXAMPLE 중요한 것 DPL란 세그먼트에 접근 가능한 레벨을 말한다. * GDTR ( GLOBAL DESCRIPTOR TABLE REGISTER ) GDTR은 GDT (Global Descriptor Table)을 정의하기 위한 레지스터이다. GDT의 용도는 무엇인가? 글로벌 메모리는 어떠한 태스크라도 접근 가능한 메모리를 말한다. 그리고 이를 정의하는 레지스터가 GDT이다. 하나의 GDT가 존재하며 GDT에는 LDT의 베이스주소를 계산하는 데 쓰인다. GDTR은 48 BIT로 이루어졌으며 GDTR의 32 BIT의 BASE 주소와 16 BIT의 리미트 부분으로 나누어지며 BASE는 GDT의 시작 어드레스를 말하며 리미트는 GDT의 크기를 말한다. GDT가 가지는 최대 디스크립터는 8192이다. * LDTR ( LOCAL DESCRIPTOR TABLE REGISTER ) LDTR은 16 BIT의 레지스터이고 13 BIT가 셀렉터이다. * TSS * IDT == 인터럽트 서비스에 관해 == == EXAMPLE 1. LINUX == == EXAMPLE 2. uC-OS II == = INT 13H - From BIOS - = 바이오스로 하드와 플로피를 제어할 필요가 있다. 이는 부팅 과정에서 커널을 특정 메모리에 올리는 데 사용된다. 필이 사용 된다. MBR를 복구하는 데도 가끔 사용된다. = 메모리 사이즈 구하기 = ---- [ToastOS]