부트로더 #1

부트로더를 만들어야 하는데, 어셈블리어 잘 모르는데 난감하다. 몇 번 훑어 본 걸로 만들 수 있을 지 모르겠다. 다른 부트로더를 참조해서 만들어야 겠다. 그래 (ㅠㅠ 나의 영혼이여~~ ) 근데, 부트로더는 어떻게 실행 할까? 라는 궁금증이 생겼다. 자 검색..검색..

음… 대충 컴퓨터가 전원이 켜질 경우 , 저장 매체의 첫 번째 섹터에서 512 바이트를 정해진 메모리에 로딩하고 해당 메모리를 프로그램으로 인식하고 실행한다. 라고 이해했다. 그러니까 첫 번째 섹터 512바이트를 읽어서 그걸 실행한다는 거군. 쉽네. 근데 왜 512바이트지?? 검색..검색.. 흠 못 찾겠다.

자 , 그러면 프로그래밍 한번 해보자!!! 아직, 부트로더 설계도 제대로 잡지 않았는데…음… 흠.

그냥 HELLO 한번 찍어 보자.

   1: mov ax, 0    ; ax 레지스터를 0 으로 초기화 한다.
   2: mov ds, ax   ; ds 세그먼트 레지스터를 0으로 초기화 한다.
   3: mov es, ax   ; es 세그먼트 레지스터를 0으로 초기화 한다.

아직 여기밖에 모르겠다. 화면에 출력하려면 어떻게 하지?? 히유!! 답답하다…또 검색질 하자.

어셈블리어를 이용해서 화면에 글자를 출력하려면 BIOS 인터럽트 를 이용해야 한다고 하네.. 그래 인터럽트 한번 더 뒤져보자.

http://ko.wikipedia.org/wiki/%EB%B0%94%EC%9D%B4%EC%98%A4%EC%8A%A4_%EC%9D%B8%ED%84%B0%EB%9F%BD%ED%8A%B8_%ED%98%B8%EC%B6%9C 여기에 인터럽트 테이블 모아놓은 게 있네. INT 10h 이용하면 되겠다.

mov al, ‘a’
mov ah, 0x0E
int 10h

이걸 이용해서 다시 프로그래밍 한다.

	cli				; 인터럽트 발생안되게 설정
	xor ax,ax		; ax 0으로 초기화 한다. ax xor ax 어차피 0이다.
	mov ds, ax		; ds 세그먼트 레지스터를 0 으로 초기화 한다.
	mov es, ax		; es 세그먼트 레지스터를 0 으로 초기화 한다.
	sti				; 인터럽트 발생 설정

	lea si, [HELLO_MSG]	; HELLO_MSG 위치 주소
	call PRINT			; PRINT 함수 호출

	
PRINT:
	pusha				; 모든 레지스터를 스택에 넣는다.
PRINT_LOOP:
	mov al, [si]		; al에 글자 하나 저장한다.
	inc si				; si 주소를 증가한다.
	or al, al			; or 연산. 
	jz PRINT_END		; 문자열 끝이 or 연산이 0 이라면. 종료
	mov ah,0x0E			; ah = 0xE
	int 0x10			; 인터럽트 0x10h
	jmp PRINT_LOOP		; 다음 문자 출력 루프	

PRINT_END:
	popa				;모든 레지스터 스택에서 뺀다.
	ret					;호출 한곳으로 리턴.

HELLO_MSG:
	db "HELLO MY BOOTLOADER", 0x00

자 코드 입력은 했고 , 컴파일 해야지~~~^^

nasm –fbin –o BOOTLOADER BOOTLOADER.ASM

캬~~ 에러도 없다. BOOTLOADER 라는 파일이 생성 되었다.

자 이제 이걸 첫 번째 섹터에 복사해 주면 된다.  아~ 난 가상이미지 파일인데?? 어떻게 이걸 복사하지?? 아놔!!! ..흠…이미지 파일이니까 그냥 이미지 파일 찾아서 해당 첫 번째에다가 복사하면 되나?? 생각 난 김에 해보자!! 근데 이거 원… 가상 이미지 파일 있는 위치를 모르겠네 ㅡㅡ;;;

1. Windows Virtual PC 를 실행한다.
2. 생성한 가상 컴퓨터를 선택한다.
3. 설정 을 클릭한다.
4. 하드 디스크 1을 선택한다.
5. 가상 이미지 파일 위치를 찾았다!

 자 , vhd 확장자의 이미지 파일을 찾았다. ㅎㅎ 이제 에디터로 불러야지~~. 음… 울트라 에디터로 로딩할 까, Visual Studio 로 로딩 할까?? 아무래도 복사해야 하니 Visual Studio 에서 로딩 해야 할것 같다. 아악!! 128MB 다. 왜 이렇게 크게 만들었을까 ..ㅠㅠ 다시 만들까?? 귀찮다!!! 그냥 읽어 버렷!

깔끔하게 헥사뷰어 로 나온다. 울트라 에디트 보단 이게 좋지~^^ 아 부트로더 도 읽어야지~~Visual Studio에 부트로더 도 읽어 준다. 탭으로 왔다 갔다 하면 편하겠네..부트로더 헥사뷰어에서 코드를 이제 복사한다. 컴퓨터가 512바이트를 읽는다고 했으니, 512바이트를 복사하면 되겠다. 라인이 1f0까지 쭉 내려서 복사한다. 그리고 이미지 파일 헥사뷰어에서 똑같이 1f0 라인까지 선택 후, 붙이기 한다. 그리고 저장.!!!!

긴장된다. Windows Virtual PC 실행해서 가상 컴퓨터 작동해봐야지~~

한참을 기다려도 실행 안된다. 검은 화면…..이미지 파일 첫 부분에 파일 붙이기 하는게 안되는 건가?? 흠.. 인터넷에서 돌아다니는 부트로더로 컴파일 해서 복사, 붙이기 하니 화면이 뜬다. 이미지 파일 첫 부분에 붙이기 하는건 되는건가 보다. 내가 만든 코드는 아니지만 가상 컴퓨터 화면에 뭔가 출력은 되니, 쪼금 나도 희망이 생긴다. 음.. 뭐가 문제지?? 되는 부트로더 랑 비교해 보자!!

크게 다른 부분은 첫 부분하고 끝 부분이다.

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

이건 또 무슨 문법이야 ? 하고 검색해 보니, times 는 뭘 반복할 때 쓴다고 한다. $는 현재 위치를 나타내는 거고, $$줄 처음 위치를 나타내는 거란다. 그러면 저 명령어 들의 하는 짓은??? 그냥 510까지 0으로 채우는 짓이란다. 즉 내가 만든 코드는 50 바이트 밖에 안된다. 510-50 = 460 바이트를 0으로 다 채운다는 것이다. 어차피 0으로 다 채워져 있는데 뭘!! 흠.. 그리고 dw 0xAA55는 510 이후에 AA55라고 쓰기 위해서란다. 왜???? 컴퓨터가 512 바이트를 읽고 0xAA55 저놈이 있나 없나 체크 한단다!! 없으면 실행 안 해 준다네…

흠.. 그러니까 512 바이트 중 끝에 0xAA55가 있어야지 우선 실행해 준다는 거네. 그러면 코드에 times랑 0xAA55 넣고 컴파일….다시 가상 PC 작동…..오~~~~~~~~~~~~~~~~~ 뭔가 나온다!!!

아드래날린이 왕성하게 분비 되는지 흥분된다. 하하하 . 흠 근데 왜 글자가 안나오고 쓰레기값이 나오냐?? 코드 문제인가? 흠.. 동작하는 부트로더랑 비교해 봐야겠네…

첫부분에

org 0x7C00
bits 16

이 있다. 뭐 뒤에 쓰잘데기 없이 점프 명령어 있긴 한데 뭐 필요 없는 작업인것 같고… 요 두넘이 틀리다. 또 뭐하는 놈들이냐?? 검색..검색…(검색질도 지겹다 …)

ORG 0x7C00 : 컴퓨터가 내가 만든 부트로더를 0x7C00 메모리 위치에다가 로딩하는데, 내 부트로더는 데이터 변수 쓸때 그 데이터 변수 위치가 0으로 시작된 위치에 있으므로 찾지 못한다. 고로 첫줄에 똭!!!! 0x7C00 부터 시작 되게 하면 그 데이터를 쓸 수 있게 해준단다!

BITS 16 : 내가 작성하는게 16비트에서 작동하는 코드를 사용한다는 명령어란다. 흠!

뭐 이리 어렵나~~ 여튼 추가…

ORG 0x7C00 
BITS 16

    cli                ; 인터럽트 발생안되게 설정 
    xor ax,ax        ; ax 0으로 초기화 한다. ax xor ax 어차피 0이다. 
    mov ds, ax        ; ds 세그먼트 레지스터를 0 으로 초기화 한다. 
    mov es, ax        ; es 세그먼트 레지스터를 0 으로 초기화 한다. 
    sti                ; 인터럽트 발생 설정

    lea si, [HELLO_MSG]    ; HELLO_MSG 위치 주소 
    call PRINT            ; PRINT 함수 호출

    jmp $

    
PRINT: 
    pusha                ; 모든 레지스터를 스택에 넣는다. 
PRINT_LOOP: 
    mov al, [si]        ; al에 글자 하나 저장한다. 
    inc si                ; si 주소를 증가한다. 
    or al, al            ; or 연산. 
    jz PRINT_END        ; 문자열 끝이 or 연산이 0 이라면. 종료 
    mov ah,0x0E            ; ah = 0xE 
    int 0x10            ; 인터럽트 0x10h 
    jmp PRINT_LOOP        ; 다음 문자 출력 루프   

PRINT_END: 
    popa                ;모든 레지스터 스택에서 뺀다. 
    ret                    ;호출 한곳으로 리턴.

HELLO_MSG: 
    db "HELLO MY BOOTLOADER", 0x00

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

나 울뻔 했다…된다..

HELLO MY BOOTLOADER

화면에 출력된다. 검색 질 하느라 시간 보냈는데 출력이 되니 기쁘다. 이제 커널 파일 만들어서 부트로더에서 로딩시키고 커널 실행시키면 되겠다. 하하 이제 C 로 넘어간다. 알지도 못하는 어셈블리어로 벗어 난다니 더 기쁘다.

'프로그래밍 > OS 만들기' 카테고리의 다른 글

OS 만들기 #6 - MBR  (0) 2013.08.14
OS 만들기 #5 - 부트로더  (0) 2013.08.14
OS 만들기 #4 - 부트로더  (0) 2013.08.14
OS 만들기 #2  (0) 2013.08.14
OS 만들기 #1  (0) 2013.08.14

+ Recent posts