본문 바로가기
study

[OS만들기]BOOTLOADER->KERNEL 시도...

by pwnhub 2024. 2. 24.

 

이전에 만든 부트로더에 추가하여, 특정 섹션을 메모리에 올리는 것을 시도함

 

[org 0x10000]
[bits 16]

mov ax, 0xB800
mov es, ax

mov byte[es:4], 'i'
mov byte[es:5], 0x09
mov byte[es:6], 'h'
mov byte[es:7], 0x09

jmp $

times 512-($-$$) db 
[org 0]
[bits 16]

jmp 0x07C0:start

start:

mov ax, 0xB800
mov es, ax

mov byte[es:0], 'h'
mov byte[es:1], 0x09
mov byte[es:2], 'i'
mov byte[es:3], 0x09
	

jmp 0x1000:0

times 510-($-$$) db 0
dw 0xAA55

 

이렇게 작성하고

 

nasm -f bin -o boot.img boot.asm

nasm -f bin -o sector.img sector.asm

컴파일해주고

 

cat boot.img sector.img > out.img

합쳐주면 out.img가 생긴다.

 

하지만 작동하지 않았다.

 

[org 0]
[bits 16]

jmp 0x07C0:start

start:

mov ax, 0xB800
mov es, ax

mov byte[es:0], 'h
mov byte[es:1], 0x09
mov byte[es:2], 'i'
mov byte[es:3], 0x09

read:
	mov ax, 0x1000
	mov es, ax
	mov bx, 0 ; 0x1000:0000 주소로 읽어 => 물리주소 0x10000

	mov ah, 2 ; 디스크에 있는 데이터를 es:bx의 주소로
	mov al, 1 ; 1섹터를 읽을 것이다
	mov ch, 0 ; 0번째 실린더
	mov cl, 2 ; 2번째 섹터부터 읽기 시작한다
	mov dh, 0 ; 헤드는 0
	mov dl, 0 ; 플로피 디스크 읽기 
	int 13h
	
	jc read ; 에러나면 다시
	
jmp 0x1000:0

times 510-($-$$) db 0
dw 0xAA55

이렇게 수정하면 된다.

해결 : [디스크 -> 메모리] 로드하는 부분을 작성해야한다.

 

 

[org 0x11000]
[bits 16]

mov ax, 0xB800
mov es, ax

mov byte[es:4], 'i'
mov byte[es:5], 0x09
mov byte[es:6], 'h'
mov byte[es:7], 0x09

jmp $

times 512-($-$$) db 
[org 0]
[bits 16]

jmp 0x07C0:start

start:

mov ax, 0xB800
mov es, ax

mov byte[es:0], 'h'
mov byte[es:1], 0x09
mov byte[es:2], 'i'
mov byte[es:3], 0x09

read:
	mov ax, 0x1100
	mov es, ax
	mov bx, 0 ; 

	mov ah, 2 ; 디스크에 있는 데이터를 es:bx의 주소로
	mov al, 1 ; 1섹터를 읽을 것이다
	mov ch, 0 ; 0번째 실린더
	mov cl, 2 ; 2번째 섹터부터 읽기 시작한다
	mov dh, 0 ; 헤드는 0
	mov dl, 0 ; 플로피 디스크 읽기 
	int 13h
	
	jc read ; 에러나면 다시
	
jmp 0x1100:0

times 510-($-$$) db 0
dw 0xAA55

이 코드도 작동한다. 

 

여기서 한참을 삽질했는데, 위 코드의 수정사항은 메모리 적재 위치를 0x11000으로 하도록 한 것이다.

16bit환경에서 주소 표기방식을 잘못 이해했기 때문에 한참을 헤매었다.

 

----삽질 기록----

메모리 할당이 의도한 대로 되지 않았음

cat 1.img 2.img > 3.img

이렇게 하면 제대로 된다.

그래도 해결이 안되는 부분이 있었다.

지피티가 살려줬다알려줬다

라고 한다.

-----------------------------끝------------------

 

삽질을 바탕으로 잘못된 이해를 바로잡았다...

 

; Boot.asm
[org 0]
[bits 16]

jmp 0x07C0:start

start:
mov ax, cs
mov ds, ax
mov es, ax

mov ax, 0xB800
mov es, ax

mov byte[es:0], 'h'
mov byte[es:1], 0x09
mov byte[es:2], 'i'
mov byte[es:3], 0x09

read:
	mov ax, 0x1000
	mov es, ax
	mov bx, 0 ; 0x1000:0000 주소로 읽어 => 물리주소 0x10000

	mov ah, 2 ; 디스크에 있는 데이터를 es:bx의 주소로
	mov al, 1 ; 1섹터를 읽을 것이다
	mov ch, 0 ; 0번째 실린더
	mov cl, 2 ; 2번째 섹터부터 읽기 시작한다
	mov dh, 0 ; 헤드는 0
	mov dl, 0 ; 플로피 디스크 읽기 
	int 13h
	
	jc read ; 에러나면 다시

	mov dx, 0x3F2 ;플로피디스크 드라이브의
	xor al, al	; 모터를 끈다
	out dx, al 
	
	cli

lgdt[gdtr]
	
mov eax, cr0
or eax, 1
mov cr0, eax
	
jmp $+2
nop
nop

mov bx, DataSegment
mov ds, bx
mov es, bx
mov fs, bx
mov gs, bx
mov ss, bx

jmp dword CodeSegment:0x10000

gdtr:
dw gdt_end - gdt - 1
dd gdt+0x7C00

gdt:

	dd 0,0 ; NULL 세그
	CodeSegment equ 0x08
	dd 0x0000FFFF, 0x00CF9A00 ; 코드 세그
	DataSegment equ 0x10
	dd 0x0000FFFF, 0x00CF9200 ; 데이터 세그
	VideoSegment equ 0x18
	dd 0x8000FFFF, 0x0040920B ; 비디오 세그

gdt_end:

times 510-($-$$) db 0
dw 0xAA55
; Sector2.asm
CodeSegment equ 0x08
DataSegment equ 0x10
VideoSegment equ 0x18

[org 0x10000]
[bits 32]

mov ax, VideoSegment
mov es, ax

mov byte[es:0x08], 'P'
mov byte[es:0x09], 0x09

jmp $

times 512-($-$$) db 0

 

Boot.asm에서 hi를 찍은 후 -> 하드디스크 읽기를 통해 섹터2를 0x10000에 적재 -> 16비트 환경을 32비트 환경으로 바꾸고 -> Sector2.asm(0x10000)으로 jmp 통해 이동 -> Sector2.asm에서 P 출력

하는 코드이다.

직접 작성한 코드가 아니라, 이해하는데 어려움이 있었다.

https://itguava.tistory.com/15?category=630867

 

[OS 개발 10] 32비트 커널 로더(4) - 커널 구현과 분석

1. 부트로더에서 커널 구현부로의 점프 앞서 언급한대로, 부트로더에서 커널 구현부로 넘어가는 부분을 우선 구현해야할 것입니다. 다음 코드를 보시죠. 위 코드는 부트로더를 확장하여 작성한

itguava.tistory.com

여기를 참고하면 이해가 쉽다.

결국 이 내용을 이해하면 끝이다.

prefix에 대해서는 나중에 따로 정리할 예정이다.