I use QEMU to run my bootloader program. In bootloader, I read the sysloader and kernel data into the 0x8000 location
bootloader.S:
#include "realmode_def.h"
#This code reads 25 sectors of the image file, prints a string, and jumps to 0x8000
.code16
.text
ljmp $BOOTSEG, $_start
_start:
mov $0, %ax
mov %ax, %ds
mov %ax, %es
mov $STACK_BASE, %ax #STACK_BASE 0x070b
mov %ax, %ss
mov $0x00ff, %sp
#
hd_load_setup:
mov $0x1f2, %dx
mov $SETUP_SECTIORS_LEN, %ax #SETUP_SECTIORS_LEN 25
out %al, %dx
mov $0x1f3, %dx
mov $START_SECTORS_BASE, %eax #START_SECTORS_BASE 1
out %al, %dx
mov $8, %cx
shr %cl, %eax
mov $0x1f4, %dx
out %al, %dx
shr %cl, %eax
mov $0x1f5, %dx
out %al, %dx
shr %cl, %eax
and $0x0f, %al
or $0xe0, %al
mov $0x1f6, %dx
out %al, %dx
mov $0x1f7, %dx
mov $0x20, %al
out %al, %dx
not_ready:
in %dx, %al
and $0x88, %al
cmp $0x08, %al
jnz not_ready
mov $SETUP_SECTIORS_LEN, %ax
mov $256, %dx
mul %dx
mov %ax, %cx
mov $0x1f0, %dx
mov $SETUP_LOAD, %bx #SETUP_LOAD 0x8000
go_on_read:
in %dx, %ax
mov %ax, (%bx)
add $2, %bx
loop go_on_read
load_system:
call print_msg
ljmp $SETUP_SEG, $0 #SETUP_SEG 0x0800
print_msg:
mov $0x07c0, %ax
mov %ax, %es
mov $0x03, %ah
xor %bh, %bh
int $0x10
mov $23, %cx
mov $0x0007, %bx
mov $msg1, %bp
mov $0x1301, %ax
int $0x10
ret
msg1:
.byte 13,10
.ascii "OS is booting ..."
.byte 13,10,13,10
_end:
.org 510
.word 0xAA55
Makefile:
CC = gcc
AS = as --32
LD = ld
CFLAGS = -fno-pic -static -fno-builtin -fno-strict-aliasing -O2 -Wall -ggdb -m32 -fno-omit-frame-pointer -fno-stack-protector -fstrength-reduce
LDFLAGS = -m elf_i386 -T kernel.ld
OBJCOPY = objcopy
STRIP = strip
AR = ar
bootloader:bootblock sysloader main make_kernel
bootblock:
@$(CC) $(CFLAGS) -O -nostdinc -I. -c bootloader_hd.S
@$(LD) $(LDFLAGS) -o bootloader -Ttext 0 bootloader_hd.o
@$(OBJCOPY) -R .pdr -R .comment -R.note -S -O binary bootloader
sysloader:
@$(CC) $(CFLAGS) -O -nostdinc -I. -c sysloader.S
@$(LD) $(LDFLAGS) -o sysloader -Ttext 0x8000 sysloader.o
@$(OBJCOPY) -R .pdr -R .comment -R.note -S -O binary sysloader
main:
@$(CC) $(CFLAGS) -c main.c -o main.o
@$(LD) $(LDFLAGS) -o kernel_img main.o
make_kernel:
@dd if=/dev/zero of=kernel.img bs=512 count=10000
@dd if=bootloader of=kernel.img bs=512 count=1 conv=notrunc
@dd if=sysloader seek=1 of=kernel.img conv=notrunc
@dd if=kernel_img of=kernel.img seek=4 conv=notrunc
I run my kernel.img using the following command
qemu-system-x86_64 -drive file=kernel.img,index=0,media=disk,format=raw -s -S
I track and debug in GDB, and after running the last instruction of the bootloader, I check its memory data at 0x8000
0x8000: 0x8ec031fa 0xe4c08ed8 0xe6020c92 0x16010f92
0x8010: 0x200f810c 0xc88366c0 0xc0220f01 0x088021ea
0x8020: 0x10b86600 0x8ed88e00 0x66d08ec0 0x8e0000b8
0x8030: 0xb9e88ee0 0x00000400 0x001000b8 0x0000c700
0x8040: 0x83000000 0xf5e204c0 0x001000b8 0x10000500
0x8050: 0xc3890000 0xa307c883 0x00001000 0x001c00a3
0x8060: 0x0400b900 0x00be0000 0xba000000 0x00000007
0x8070: 0x89b33c8d 0x00c28117 0x46000010 0x00b8f2e2
0x8080: 0x0f000010 0x200fd822 0x00000dc0 0x220f8001
0x8090: 0x7bffbcc0 0xc0310000 0xc931db31 0x00b8d231
0x80a0: 0x66000088 0x8b2a508b 0xc3811c58 0x00008800
0x80b0: 0x2c488b66 0x003c038b 0x73ff1774 0x04438b10
0x80c0: 0x00880005 0x73ff5000 0x0011e808 0xc4830000
0x80d0: 0xe2d3010c 0x8800bbdf 0x438b0000 0xfce0ff18
0x80e0: 0x51e58955 0x8b087d8b 0x4d8b0c75 0x59a4f310
0x80f0: 0x9066c35d 0x00000000 0x00000000 0x0000ffff
0x8100: 0x00cf9a00 0x0000ffff 0x00cf9200 0x80f40017
0x8110: 0x00000000 0x00000000 0x00000000 0x00000000
0x8120: 0x00000000 0x00000000 0x00000000 0x00000000
...
0x8600: 0x00000000 0x00000000 0x00000000 0x00000000
0x8610: 0x00000000 0x00000000 0x00000000 0x00000000
0x8620: 0x00000000 0x00000000 0x00000000 0x00000000
0x8630: 0x00000000 0x00000000 0x00000000 0x00000000
I found that the sysloader was loaded to 0x8000, but the data in the elf section after it was not correctly loaded to 0x8600, and all subsequent data is 0
Use xxd to view the data distribution of kernel.img:
00000000: ea05 00c0 07b8 0000 8ed8 8ec0 8ee8 b8b0 ................
...
000001f0: 0000 0000 0000 0000 0000 0000 0000 55aa ..............U.
00000200: fa31 c08e d88e c0e4 920c 02e6 920f 0116 .1..............
00000210: 0c81 0f20 c066 83c8 010f 22c0 ea21 8008 ... .f...."..!..
...
000007f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000800: 7f45 4c46 0101 0100 0000 0000 0000 0000 .ELF............
...
00001800: 5589 e5fa fb31 c05d c371 0000 0004 0000 U....1.].q......
...
When I ran it in Bochs, it correctly loaded the data of kernel.img into memory
0x0000000000008600 <bogus+ 1536>: 0x464c457f 0x00010101 0x00000000 0x00000000
0x0000000000008610 <bogus+ 1552>: 0x00030002 0x00000001 0xc0100000 0x00000034
0x0000000000008620 <bogus+ 1568>: 0x0000136c 0x00000000 0x00200034 0x00280002
0x0000000000008630 <bogus+ 1584>: 0x0009000c 0x00000001 0x00001000 0xc0100000
0x0000000000008640 <bogus+ 1600>: 0x00100000 0x00000009 0x00000009 0x00000005
0x0000000000008650 <bogus+ 1616>: 0x00001000 0x6474e551 0x00000000 0x00000000
...
0x0000000000009600 <bogus+ 5632>: 0xfae58955 0x5dc031fb 0x000071c3 0x00000400
0x0000000000009610 <bogus+ 5648>: 0x04000000 0x00000c01 0x00050c00 0x00a50000
0x0000000000009620 <bogus+ 5664>: 0x00000000 0x00000000 0x00000000 0x73020000
0x0000000000009630 <bogus+ 5680>: 0x01006974 0x63020307 0x0100696c 0x00030302
...
I want to know how to use QEMU correctly to run kernel.img