시스템 메모리 크기 구하기(BIOS)

5496 단어 운영체제OSOS

현재까지의 OS 모습이다. 32비트 보호모드에서 IA-32e(64비트)모드로 넘어갈 준비를 하고 있다.
메모리의 크기를 구하는 코드가 책에서는 직접 접근하여 값을 기록하는 식으로 설명이 되있었는데, 이 방법이 마음에 안들었다. cpu-z 같은 프로그램에서는 메모리가 몇번째 슬롯에 꽃혔는지도 알 수 있는데 이런 방법은 너무 별로라고 생각했다.

바이오스 인터럽트로 구하기

가장 간편한 방법이다. eax = 0xE820 일 때 0x15번 인터럽트로 현재 시스템의 메모리 맵을 구할 수 있다. 아래 그림과 같이 Base-Length-Type으로 저장된다.

사용방법은 EAX 에 0xE820 세팅, ECX에 24(10진수) 세팅, EDX 에 0x534D4150 세팅,
ES:DI 에 메모리 맵이 저장될 주소 세팅 후 0x15 인터럽트를 호출한다. 종료 기준은 EBX==0 이다.
메모리 맵은 Base-Length-Type 으로 저장되며 총 24바이트다. 따라서 한번 호출이후 DI도 24씩 늘려준다.
물론 바이오스 인터럽트인 만큼 16비트 리얼모드에서 호출해야 한다. 아래 코드는 0x7E00 에는 맵 개수, 0x7E08 부터 메모리 맵을 저장한다.

DETECT_INIT:
    mov ebx, 0 ; ebx 초기화
    mov edx, 0x534D4150	; 매직 넘버
    mov ax , 0x7E0
    mov es, ax
    mov di, 0
    mov byte [es:0], 0 ; 0x7E00 = 맵 개수 
    add di, 0x8 ; 0x7E08 = 맵 시작
DETECT_ENTRY:
    mov eax, 0xE820
    mov ecx, 24
    int 0x15
    add byte [es:0], 1
    cmp ebx, 0
    je DETECT_END
    add di, 24
    jmp DETECT_ENTRY
DETECT_END:

이후 보호모드로 진입해서 해당 주소의 값을 읽으면 된다. 간단한 C언어 코드로는 아래와 같은 코드를 작성할 수 있겠다.

DWORD kGetTotalMemorySize32()
{
    int mapCount = *(int*)(0x7E00); //메모리 맵 개수
    int* mapAddr = (int*)(0x7E08);
    int totalSize = 0;
    for(int i = 0; i< mapCount; i++)
    {
        totalSize += *(mapAddr+2);
        mapAddr += 6;
    }
    return totalSize;
}

Serial Presense Detection

CPU-Z, HWMoitor 같은 프로그램들이 사용하는 방식이다. 컴퓨터를 커면 메인보드의 장치들이
'나 동작합니다~' 하고 정보를 보내는데, 이때 보낸 정보를 활용하는 것이다.
인데... 아직 잘 모르겠다. PCI Configuration Space 를 통해서 접근을 하는 것 같은데. 나중에 64비트 OS의 기반이 다져지면 정리해서 올려보려고 한다.
흠.. PCI 는 저번에 virtual box 원데이 익스플로잇 할 때 좀 공부해둬서 다행이다 ㅋㅋ

좋은 웹페이지 즐겨찾기