qemu, x86 부팅 관련 질문
글쓴이: hongwoo / 작성시간: 화, 2009/05/26 - 5:53오후
안녕하세요~
김범준씨가 쓴 "OS와 커널의 구조와 원리"를 따라해보고 있습니다.
vmware와 qemu를 사용해서 테스트하고 있는데요..,
원인을 알 수 없는 이상한 현상이 있어서., 도움받고자 이렇게 글을 올립니다.
간단하게 x86 부팅해서 화면에 배경과 글자를 찍는 코드입니다.
boot.asm
[org 0] jmp 07C0h:start start: mov ax, cs mov ds, ax mov es, 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 ; ES:BX = 1000:0000 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 ; 에러가 나면, 다시 함. jmp 0x1000:0000 ; kernel.bin 이 위치한 곳으로 점프한다. msgBack db '.', 0x67 times 510-($-$$) db 0 dw 0AA55h
kernel.asm
[org 0] [bits 16] start: mov ax,cs ; CS 에는 0x1000 이 들어 있다. 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
Makefile
BOOT_SRCS = boot.asm kernel.asm BOOT_IMG = floppy.img all:$(BOOT_IMG) $(BOOT_IMG) : $(BOOT_SRCS) nasm -f bin -o boot.img boot.asm nasm -f bin -o kernel.img kernel.asm cat boot.img kernel.img > $@ clean: rm -f *.o *.img *.tmp *.txt *.map
이걸 make 해서 qemu에서 이렇게 돌려봤습니다. (ubuntu 9.04)
qemu -m 64 -fda ./floppy.img -boot a
We are in kernel program이라는 스트링이 안나옵니다.
같은 이미지를 윈도우에서 VMware로 돌리면 잘 나옵니다.
qemu monitor 모드에서 분석을 해보려고 하는데요.
xp /10hi 0x10000 에 kernel.asm의 start에 해당하는 코드가 있을거라고 생각했는데.. 예상한 결과가 없습니다.
더 이상한건 xp /10hi 0x7c00 으로 덤프뜬 결과가 매번 다릅니다. ㅠㅜ
이것 저것 코드 바꿔가며 테스트 하고 있는데.,
아직 원인을 찾지 못했습니다. 뭘까요 ??
Forums:
kernel.img 가 512 byte가
kernel.img 가 512 byte가 안되서... read에서 두번째 섹터를 읽으려고 할 때, 엉뚱한걸 읽어오는게 문제였나봅니다.
"times 512-($-$$) db 0" 를 kernel.asm의 마지막에 넣어서 두번째 섹터를 512로 하니까, 제대로 0x1000:0000으로 점프를 하네요.
음.. x86에서 0x13 인터럽트에 대해서 좀 보면 해답이 나올까요 ? ~
-----------------------------
in the real-time scheduler !
저도 막혔다가 해결했네요
http://anster.egloos.com/62843
여기서 찾았는데.
마지막에 times로 해서 0을 채워줘야 되더라고요
안그러면 커널 자체가 로드가 안되네요.
댓글 달기