Bootloader 不会加载内核
Bootloader won't load the kernel
其实我做了一个两阶段的bootloader,因为我使用VESA BIOS扩展设置了视频模式为1920px*1080px(这需要超过512字节。)
对现在我正在尝试调用我自己的内核来开始绘制像素等。但是它没有用。
我的引导加载程序基于 Michael Petch 的代码,来自这个
的答案
bootloader.asm:
%include "stage2info.inc"
STAGE2_LOAD_SEG equ STAGE2_ABS_ADDR >> 4
STAGE2_LBA_START equ 1
STAGE2_LBA_END equ STAGE2_LBA_START + NUM_STAGE2_SECTORS
[BITS 16]
[ORG 0x7c00]
%include "BPB.inc"
%include "error.asm"
bootloader_main:
xor ax, ax
mov ds, ax
mov ss, ax
mov sp, 0x7c00
cld
load_stage2:
mov [bootDevice], dl
mov di, STAGE2_LOAD_SEG
mov si, STAGE2_LBA_START
jmp check_for_last_lba
read_sector:
call lba_to_chs
mov es, di
xor bx, bx
retry:
mov ax, 0201h
int 13h
jc disk_error
success:
add di, 512>>4
inc si
check_for_last_lba:
cmp si, STAGE2_LBA_END
jl read_sector
stage2_loaded:
mov ax, STAGE2_RUN_SEG
mov ds, ax
mov es, ax
jmp STAGE2_RUN_SEG:STAGE2_RUN_OFS
lba_to_chs:
push ax
mov ax, si
xor dx, dx
div word[sectorsPerTrack]
mov cl, dl
inc cl
xor dx, dx
div word[numHeads]
mov dh, dl
mov dl, [bootDevice]
mov ch, al
shl ah, 6
or cl, ah
pop ax
ret
bootDevice: db 0x00
times 510 - ($-$$) db 0
DW 0xAA55
NUM_STAGE2_SECTORS equ (stage2_end - stage2_start + 511) / 512
stage2_start:
incbin "stage2.bin"
stage2_end:
stage2.asm:
%include "stage2info.inc"
[BITS 16]
[ORG STAGE2_RUN_OFS]
start:
;graphics stuff here...
call load_kernel
cli
lgdt[gdt_descriptor]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp 0x8:kernel_entry
[BITS 32]
kernel_entry:
mov ax, 0x10
mov ss, ax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ebp, 0x90000
mov esp, ebp
call KERNEL_OFFSET
jmp $
[BITS 16]
load_kernel:
mov bx, KERNEL_OFFSET
mov dh, 15
mov dl, 0
mov ah, 0x02
mov al, dh
mov ch, 0x00
mov dh, 0x00
mov cl, 0x02
int 0x13
ret
GDT:
dq 0
dw 0xFFFFF
dw 0x0
db 0x0
db 10011010b
db 11001111b
db 0x0
dw 0xFFFFF
dw 0x0
db 0x0
db 10010010b
db 11001111b
db 0x0
gdt_descriptor :
dw $ - GDT - 1
dd GDT
incbin "../kernel/kernel.bin"
VESAInfo db 'VBE3'
times 508 db 0
MODEInfo times 256 db 0
ModeInfoBlock times 256 db 0
KERNEL_OFFSET equ 0x1000
%include "error.asm"
stage2info.asm:
STAGE2_ABS_ADDR equ 0x07e00
STAGE2_RUN_SEG equ 0x0000
STAGE2_RUN_OFS equ STAGE2_ABS_ADDR
kernel.asm:
[bits 32]
jmp $
然后我构建如下图像:
#!/bin/bash
nasm -f bin stage2.asm -o stage2.bin
nasm -f bin ../kernel/kernel.asm -o ../kernel/kernel.bin
nasm -f bin bootloader.asm -o bootloader.bin
dd if=/dev/zero of=disk.img bs=512 count=2880
dd if=bootloader.bin of=disk.img conv=notrunc
qemu-system-i386 -fda disk.img -boot a
知道为什么它不起作用吗?
通过进入保护模式并包含kernel.asm
文件而不是二进制文件解决了问题。
方法如下 (stage2.asm):
%include "stage2info.inc"
[BITS 16]
[ORG STAGE2_RUN_OFS]
start:
pusha
mov ah, 0x00
mov al, 0x03
int 10h
popa
mov ax, 4F00h
mov di, VESAInfo
int 10h
cmp al, 4Fh
jne VBE_error
mov si, [VESAInfo + 0Eh]
loop:
mov ax, [VESAInfo + 10h]
mov es, ax
mov dx, word[es:si]
cmp dx, 0FFFFh
je got_mode
add si, 2
mov cx, dx
mov ax, 4F01h
mov di, MODEInfo
int 10h
cmp al, 4Fh
jne loop
mov ax, word[MODEInfo]
bt ax, 0
jnc loop
bt ax, 4
jnc loop
bt ax, 7
jnc loop
mov ax, word[MODEInfo + 12h]
cmp ax, 1920
jne loop
mov ax, word[MODEInfo + 14h]
cmp ax, 1080
jne loop
xor ax, ax
mov al, byte[MODEInfo + 19h]
cmp ax, 24
jne loop
got_mode:
mov ax, 4F01h
mov cx, dx
mov di, ModeInfoBlock
int 10h
cmp ax, 4Fh
jne VBE_error
mov ax, 4F02h
mov bx, dx
int 10h
cmp ax, 4Fh
jne VBE_error
cli
lgdt [gdt_descriptor] ;Load the global descriptor table
mov eax, cr0
or al, 1
mov cr0, eax
jmp 0x8:prepare_segments ;prepare segments
prepare_segments:
mov ax, 0x10
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
jmp kernel ;jump to the kernel in kernel.asm!
GDT:
dq 0
dw 0xFFFFF
dw 0x0
db 0x0
db 10011010b
db 11001111b
db 0x0
dw 0xFFFFF
dw 0x0
db 0x0
db 10010010b
db 11001111b
db 0x0
gdt_descriptor :
dw $ - GDT - 1
dd GDT
[BITS 32]
;We're already in the protected mode here!
%include "../kernel/kernel.asm" ;include the kernel
[BITS 16]
VESAInfo db 'VBE3'
times 508 db 0
MODEInfo times 256 db 0
%include "ModeInfoBlock.asm"
KERNEL_OFFSET equ 0x1000
%include "error.asm"
其实我做了一个两阶段的bootloader,因为我使用VESA BIOS扩展设置了视频模式为1920px*1080px(这需要超过512字节。)
对现在我正在尝试调用我自己的内核来开始绘制像素等。但是它没有用。
我的引导加载程序基于 Michael Petch 的代码,来自这个
的答案
bootloader.asm:
%include "stage2info.inc"
STAGE2_LOAD_SEG equ STAGE2_ABS_ADDR >> 4
STAGE2_LBA_START equ 1
STAGE2_LBA_END equ STAGE2_LBA_START + NUM_STAGE2_SECTORS
[BITS 16]
[ORG 0x7c00]
%include "BPB.inc"
%include "error.asm"
bootloader_main:
xor ax, ax
mov ds, ax
mov ss, ax
mov sp, 0x7c00
cld
load_stage2:
mov [bootDevice], dl
mov di, STAGE2_LOAD_SEG
mov si, STAGE2_LBA_START
jmp check_for_last_lba
read_sector:
call lba_to_chs
mov es, di
xor bx, bx
retry:
mov ax, 0201h
int 13h
jc disk_error
success:
add di, 512>>4
inc si
check_for_last_lba:
cmp si, STAGE2_LBA_END
jl read_sector
stage2_loaded:
mov ax, STAGE2_RUN_SEG
mov ds, ax
mov es, ax
jmp STAGE2_RUN_SEG:STAGE2_RUN_OFS
lba_to_chs:
push ax
mov ax, si
xor dx, dx
div word[sectorsPerTrack]
mov cl, dl
inc cl
xor dx, dx
div word[numHeads]
mov dh, dl
mov dl, [bootDevice]
mov ch, al
shl ah, 6
or cl, ah
pop ax
ret
bootDevice: db 0x00
times 510 - ($-$$) db 0
DW 0xAA55
NUM_STAGE2_SECTORS equ (stage2_end - stage2_start + 511) / 512
stage2_start:
incbin "stage2.bin"
stage2_end:
stage2.asm:
%include "stage2info.inc"
[BITS 16]
[ORG STAGE2_RUN_OFS]
start:
;graphics stuff here...
call load_kernel
cli
lgdt[gdt_descriptor]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp 0x8:kernel_entry
[BITS 32]
kernel_entry:
mov ax, 0x10
mov ss, ax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ebp, 0x90000
mov esp, ebp
call KERNEL_OFFSET
jmp $
[BITS 16]
load_kernel:
mov bx, KERNEL_OFFSET
mov dh, 15
mov dl, 0
mov ah, 0x02
mov al, dh
mov ch, 0x00
mov dh, 0x00
mov cl, 0x02
int 0x13
ret
GDT:
dq 0
dw 0xFFFFF
dw 0x0
db 0x0
db 10011010b
db 11001111b
db 0x0
dw 0xFFFFF
dw 0x0
db 0x0
db 10010010b
db 11001111b
db 0x0
gdt_descriptor :
dw $ - GDT - 1
dd GDT
incbin "../kernel/kernel.bin"
VESAInfo db 'VBE3'
times 508 db 0
MODEInfo times 256 db 0
ModeInfoBlock times 256 db 0
KERNEL_OFFSET equ 0x1000
%include "error.asm"
stage2info.asm:
STAGE2_ABS_ADDR equ 0x07e00
STAGE2_RUN_SEG equ 0x0000
STAGE2_RUN_OFS equ STAGE2_ABS_ADDR
kernel.asm:
[bits 32]
jmp $
然后我构建如下图像:
#!/bin/bash
nasm -f bin stage2.asm -o stage2.bin
nasm -f bin ../kernel/kernel.asm -o ../kernel/kernel.bin
nasm -f bin bootloader.asm -o bootloader.bin
dd if=/dev/zero of=disk.img bs=512 count=2880
dd if=bootloader.bin of=disk.img conv=notrunc
qemu-system-i386 -fda disk.img -boot a
知道为什么它不起作用吗?
通过进入保护模式并包含kernel.asm
文件而不是二进制文件解决了问题。
方法如下 (stage2.asm):
%include "stage2info.inc"
[BITS 16]
[ORG STAGE2_RUN_OFS]
start:
pusha
mov ah, 0x00
mov al, 0x03
int 10h
popa
mov ax, 4F00h
mov di, VESAInfo
int 10h
cmp al, 4Fh
jne VBE_error
mov si, [VESAInfo + 0Eh]
loop:
mov ax, [VESAInfo + 10h]
mov es, ax
mov dx, word[es:si]
cmp dx, 0FFFFh
je got_mode
add si, 2
mov cx, dx
mov ax, 4F01h
mov di, MODEInfo
int 10h
cmp al, 4Fh
jne loop
mov ax, word[MODEInfo]
bt ax, 0
jnc loop
bt ax, 4
jnc loop
bt ax, 7
jnc loop
mov ax, word[MODEInfo + 12h]
cmp ax, 1920
jne loop
mov ax, word[MODEInfo + 14h]
cmp ax, 1080
jne loop
xor ax, ax
mov al, byte[MODEInfo + 19h]
cmp ax, 24
jne loop
got_mode:
mov ax, 4F01h
mov cx, dx
mov di, ModeInfoBlock
int 10h
cmp ax, 4Fh
jne VBE_error
mov ax, 4F02h
mov bx, dx
int 10h
cmp ax, 4Fh
jne VBE_error
cli
lgdt [gdt_descriptor] ;Load the global descriptor table
mov eax, cr0
or al, 1
mov cr0, eax
jmp 0x8:prepare_segments ;prepare segments
prepare_segments:
mov ax, 0x10
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
jmp kernel ;jump to the kernel in kernel.asm!
GDT:
dq 0
dw 0xFFFFF
dw 0x0
db 0x0
db 10011010b
db 11001111b
db 0x0
dw 0xFFFFF
dw 0x0
db 0x0
db 10010010b
db 11001111b
db 0x0
gdt_descriptor :
dw $ - GDT - 1
dd GDT
[BITS 32]
;We're already in the protected mode here!
%include "../kernel/kernel.asm" ;include the kernel
[BITS 16]
VESAInfo db 'VBE3'
times 508 db 0
MODEInfo times 256 db 0
%include "ModeInfoBlock.asm"
KERNEL_OFFSET equ 0x1000
%include "error.asm"