ncloader  0.1
 모두 데이타 구조 파일들 함수 변수 타입정의 열거형 타입 열거형 멤버 매크로 그룹들 페이지들
Memory
+ Memory에 대한 협력 다이어그램:

2.1 Real Mode

이 장에서는 Real Mode 상태에서의 Memory Map 과 메모리 접근 방법, A20 Enable 방법에 대해 알아본다. 처음 IBM PC 가 등장했을 때, 16 bits 컴퓨터로 접근할 수 있는 최대 메모리 주소는 1 MB 였다. 그 중 640 KB(0 – 0x9ffff) 만을 프로그램에게 할당하고, 나머지 384 KB (0xa0000 – 0xffff) 는 BIOS 와 ISA 장치용으로 할당하였다.

다음은 메모리 구성 내용이다.

시작 주소마지막 주소영역
0x0000:0x00000x0000:0x03FFIVT (Interrupt Vector Table)
0x0000:0x04000x0000:0x04FFBDA (BIOS Data Area)
0x0000:0x05000x0000:0x7BFFFree Usable Memory
0x0000:0x7c000x0000:0x7DFFBoot program
0x0000:0x7E000x9000:0xFFFFFree usable memory
0xA000:0x00000xB000:0xFFFFVGA Video RAM
0xC000:0x00000xF000:0xFFFFBIOS ROM Memory Area
0xFFFF:0x00100xFFFF:0xFFFFFree usable memory(A20)

<표 1> Real mode 에서의 메모리 구성

IVT 는 Interrupt Vector Table 이 기록된 위치로, 인터럽트를 처리하는 핸들러들이 구현되어 있는 곳이다. (* ARM 계열 CPU 도 0번지부터 IVT 가 시작된다.) 이 IVT 에는 0으로 나누는 경우를 위한 Divide Error Handler 를 비롯하여, 시스템 타이머에 의해 CPU 에 걸린 인터럽트를 처리하는 System timer interrupt handler 등 S/W Interrupt(Trap) 부터 H/W Interrupt(Interrupt) 까지 각각에 대한 Handler Address 들이 저장된다.

Real mode 에서 정의된 Interrupt Vector Table 은 보호모드로 진입하게 되면 새로 정의한다.

지금까지 설명한 메모리 공간은 Real mode 상의 공간이다. x86 CPU 는 Real mode 와 Protoected mode 를 지원하는데, Real mode 는 옛날 시스템과의 호환을 위해 남아 있는 모드이다. (64 Bits 에서는 Long mode 가 있다.)

Real mode 에서 주소 표기 방식은 Segmentation 을 사용하고 있으며, Segment 를 4 bits shift 한 후 Offset 과 더해서 Linear address 를 얻게 된다.

Linear Address = Segment << 4 + Offset

테이블의 마지막에 있는 활용 가능 메모리에 A20 이라고 표시된 부분이 있다. PC는 0xFFFF:0x0010 ~ 0xFFFF:0xFFFF 영역을 Wrap-around 영역이라고 해서 남겨 두었다. (0x100000 ~ 0x10FFEF) (물론 남겨두고 싶어서 남겨 둔 건 아니고, 그 당시 접근 가능한 메모리 주소가 20 Bits 밖에 되지 않았으므로..)

실제로 이 영역을 접근하려고 하면, 0x0000:0x0000 영역 이후를 접근 하도록 한 것이다. 하지만 향 후 컴퓨터가 발전하면서 상위 메모리를 수용할 수 있는 램이 등장하였고, 이 영역을 사용할 수 있게 되었다. 하지만, 예전의 컴퓨터를 위해 개발된 응용프로그램 들은 새로운 영역에 대해 잘못된 계산을 할 수 있었고, 이를 방지하기 위해 A20 Gate 을 설치했다.

하위 호환성을 유지하면서, 표현 가능한 전체 주소 영역을 모두 쓰기 위해서, A20 Line 이 소개 된 것이다.

A20 Line 을 Enable 시키는 방법은 여러가지가 있지만 주로 다음과 같은 두가지 방식을 사용한다.

위에서 설명한 코드를 이용하면 A20 Gate 를 Enable 시킬 수 있다. 활성화가 제대로 되었는지를 확인하기 위한 코드는 아래와 같다.

xor ax, ax
mov bx, 0xFFFF
mov fs, ax
mov gs, bx
mov di, 0x0500
mov si, 0x0510
mov byte[FS:DI], 0x00
; Enable the A20-Gate here
mov byte[GS:SI], 0x01
cmp byte[FS:DI], 0x01
je Error

FS 세그먼트를 초기화 시키기 위해 AX 를 0 으로 만든 후, AX 레지스터 값을 FS 세그먼트에 대입했고, BX 에 0xFFFF 값을 대입한 후, GS 세그먼트에 그 값을 저장하였다.

Wrap around 영역에 값을 넣고, 0:0 영역의 값을 비교하는 것으로, A20 Gate 활성화 상태를 확인했다.

Reference site : http://www.osdever.net/tutorials/rm_addressing.php?the_id=50

이제 우리는 1 MB 영역을 넘어서는 곳도 접근할 수 있게 되었다.

2.1.1 Memory 초기화

프로그램이 동작하기 위해서는 데이터 영역과 스택 영역이 필요하다. SS, SP, BP 와 DS 를 초기화 해주는 것으로 시작된다. SS 는 Stack segment, SP는 Stack pointer, BP 는 Base pointer, DS 는 Data segment 를 의미한다. 세그먼트의 경우 즉치 값을 바로 설정할 수 없기 때문에 반드시 레지스터를 한 번 거쳐서 사용하거나 메모리에 기록된 값을 전달해 주는 방식으로 해야 한다. 메모리 맵은 위에서 설명한 공간 중 사용 가능 공간을 임의의 방식대로 적절히 나누어서 사용하면 된다. 다만 스택과 DS 를 초기화 할 때에는 인터럽트가 발생하지 못하게 설정해 두어야 한다. 스택을 변경하는 도중에 인터럽트가 발생하면 스택이 꼬일 수 있기 때문이다. 아래는 초기화와 관련된 코드이다.

cli
mov ax, STACK_SEGMENT
mov ss, ax
mov sp, STACK_SP
mov bp, sp
sti
mov ax, DATA_SEGMENT
mov ds, ax
mov es, ax

Stage 1 에서는 이정도로 Memory 를 초기화 하고, Stage 2 에서 좀 더 많은 정보를 다루기로 한다.