부트스트랩을 이용하여 커널 로드 하기
1장에서 사용한 boot.txt를 이용하여 커널을 로드하여 본다.
여기서는 2개의 파일이 필요하다. 첫번째는 boot.txt파일, 두번째는 kernel.txt 파일이 필요하다.
첫번째 파일 boot.txt의 소스는 아래와 같다
boot.txt
[org 0]
[bits 16]
jmp 0x07C0:start
start:
mov ax, cs
mov ds, ax
mov ax, 0xB800
mov es, ax
mov di, 0
mov ax, word [msgBack]
mov cx, 0x7FF
paint:
mov word [es:di], ax
add di, 2
dec cx
jnz paint
read:
mov ax, 0x1000
mov es, ax
mov bx, 0
mov ah, 2 : 디스크에 있는 데이터를 es:bx의 주소로
mov al, 1 : 1섹터를 읽는다.
mov ch, 0 : 0번째 Cylinder
mov cl, 2 : 2번째 섹터부터 읽기 시작
mov dh, 0 : Head = 0
mov dl, 0 : Drive = 0, A: 드라이브
int 0x13 : Read 시작
jc read : 에러가 날 경우 다시 함 : 이 루틴에서 에러 발생 시 CPU의 CF비트가 1로 세트됨,
1로 세트되어 있다면 erad: 번지로 점프하여 디스크 읽기를 다시 실행한다.
jmp 0x1000:0000 : kernel.bin이 위치한 곳으로 점프한다.
msgBack db '.', 0x67
times 510-($-$$) db 0
dw 0xAA55
------------------------------------------------------------------
kernel.txt
.[org 0]
[bits 16]
start:
mov ax, cs : cs에는 0x1000이 들어있다. boot.txt 파일 마지막 jmp 0x1000:0000 에서 0x1000이 cs로 들어가기 때문
mov ds, ax
xor ax, ax
mov ss, ax
lea esi, [msgKernel] : 문자열이 있는 곳의 주소를 구한다.
mov ax, 0xB800
mov es, ax : es에 0xB800을 넣는다.
mov edi, 0 : 화면의 제일 처음 부분부터 시작한다.
call printf
jmp $
printf:
push eax : 먼저 있던 eax 값을 스택에 보존해 놓는다.
printf_loop:
mov al, byte [esi] : esi가 가리키는 주소에서 문자를 하나 가져온다.
mov byte [es:edi], al : 문자를 화면에 나타낸다.
or al, al : al이 0인지 알아본다.
jz printf_end : 0이라면 print_end로 점프한다.
inc edi : 0이 아니라면 edi를 1 증가시켜
mov byte [es:edi], 0x06 : 문자색과 배경색의 값을 넣는다.
inc esi : 다음 문자를 꺼내기 위해 esi를 하나 증가
inc edi : 화면에 다음 문자를 나타내기 위해 edi를 증가
jmp printf_loop : 루프를 돈다.
printf_end:
pop eax : 스택에 보존했던 eax를 다시 꺼낸다.
ret : 호출한 부분으로 돌아간다.
msgKernel db "We are in kernel program", 0
아래와 같이 컴파일 및 copy 명령어를 통해 합친다.
커널 로드 성공!
'OS 커널의 구조와 원리' 카테고리의 다른 글
4장 : 인터럽트와 예외 - 3(키보드 인터럽트 핸들러 구현) (0) | 2015.05.06 |
---|---|
4장 : 인터럽트와 예외 - 2(하드웨어 인터럽트) (0) | 2015.05.06 |
4장 : 인터럽트와 예외 - 1 (0) | 2015.05.04 |
3장 : Protected Mode로 변환 (0) | 2015.05.04 |
1장 : 부트스트랩 (0) | 2015.04.27 |