我是一名初级汇编程序员,我正在尝试为内核编写 x86 引导加载程序。主引导加载程序似乎工作正常,但辅助引导加载程序有一些问题:当内核分区文件系统丢失/损坏或找不到内核可执行文件 (kernel.bin) 时,它不会显示错误消息。我的引导加载程序发生了一些奇怪的事情。我附上了主引导加载程序和辅助引导加载程序源代码。我真的很感激一些帮助。谢谢!
主引导加载程序:
ORG 0x7c00
BITS 16
start:
mov si, message
call print
mov ah, 2
mov al, 1
mov ch, 0
mov dh, 0
mov dl, 0x80
mov bx, 0x8000
mov cx, 3
int 0x13
jc disk_error
mov si, buffer
cmp byte [si + 0x8000], 0x00
jnz secondary_bootloader_missing
jmp 0x0000:0x8000
disk_error:
mov si, disk_error_message
call print
secondary_bootloader_missing:
mov si, secondary_bootloader_missing_message
call print
cli
hlt
print:
mov bx, 0
loop:
lodsb
cmp al, 0
je done
call _print
jmp loop
done:
ret
_print:
mov ah, 0x0E
int 0x10
ret
message:
db "Bootloader", 0x0A, 0x0A, 0
disk_error_message:
db "Disk error!", 0x0A, 0
secondary_bootloader_missing_message:
db "Secondary bootloader not found - system halted!", 0x0A, 0
buffer:
times 510-($ -$$) db 0
db 0xAA55
辅助引导加载程序:
ORG 0x8000
BITS 16
section .data
buffer db 16 dup(0)
pit_info db 16 dup(0)
active_partition_info dw 0
section .text
global start
start:
mov ah, 0x00
mov al, 0x03
int 0x10
mov si, starting_message
call print
mov ds, ax
mov es, ax
mov ah, 0x02
mov al, 0x01
mov ch, 0x00
mov dh, 0x00
mov dl, 0x80
mov bx, buffer
int 0x13
jc error_missing_pit
xor cx, cx
mov si, buffer
loop:
mov ax, [si + 0x1C]
test ax, ax
jnz found_bootable
add si, 16
inc cx
cmp cx, 0
jz no_bootable
jmp loop
found_bootable:
mov di, pit_info
mov cx, 16
rep movsb
mov ax, [si + 0x08]
mov [active_partition_info], ax
mov ax, [si + 0x0C]
mov [active_partition_info + 2], ax
mov ah, 0x02
mov bh, 0x00
mov dh, 0x01
mov dl, 0x00
int 0x10
mov si, partition_found_message
mov ax, 0x0000
mov ds, ax
call print
jmp kernel_load
error_missing_pit:
mov si, missing_pit
mov ax, 0x0000
mov ds, ax
call print
cli
hlt
no_bootable:
mov si, no_partition
mov ax, 0x0000
mov ds, ax
call print
cli
hlt
starting_message:
db "Starting the operating system...", 0x0A, 0
missing_pit:
db "Partition Table error!", 0x0A, 0
no_partition:
db "Kernel partition cannot be found - does it have the active flag?", 0x0A, 0
print:
mov bx, 0
call print_loop
ret
print_loop:
mov al, [si]
cmp al, 0
je print_done
mov ah, 0x0E
int 0x10
inc si
jmp print_loop
print_done:
ret
kernel_load:
mov ax, [active_partition_info]
add ax, 19
mov es, ax
mov bx, 0
mov ah, 0x02
mov al, 1
mov ch, 0
mov dh, 0
mov dl, 0x80
mov si, boot_sector_buffer
int 0x13
mov si, file_system_signature
mov cx, 3
repe cmpsb
jnz not_fat12
jmp search_file
not_fat12:
mov si, file_system_error_message
call print
cli
hlt
boot_sector_buffer:
times 512 db 0
file_system_signature:
db 0x55, 0xAA
file_system_error_message:
db "Unknown boot partition file system!", 0
search_file:
mov cx, 11
mov di, kernel_filename
rep cmpsb
je file_found
add bx, 32
cmp bx, 512
jae file_not_found
jmp search_file
file_found:
mov ax, 0x1000
mov cx, 8
mov dx, ax
mov bx, 0
call read_file
jmp 0x1000:0000
file_not_found:
mov si, kernel_not_found_message
call print
cli
hlt
read_file:
pusha
mov ax, cx
mov ah, 0x02
mov al, 1
mov ch, 0
mov dh, 0
int 0x13
jnc read_success
stc
popa
ret
read_success:
add dx, 512
add bx, 1
dec ax
jnz read_loop
popa
ret
read_loop:
pusha
mov ax, cx
mov ah, 0x02
mov al, 1
mov ch, 0
mov dh, 0
int 0x13
jnc read_success
stc
popa
ret
kernel_filename:
db "KERNEL BIN", 0
kernel_not_found_message:
db "Kernel file (kernel.bin) not found!", 0
partition_found_message:
db "Kernel partition found!", 0x0A, 0
我尝试运行这段代码,发现了一些错误
Bootloader 无法启动,因为有
db 0xAA55
。我将其更改为 dw 0xAA55
,我们就可以开始了。 ;)
程序读取以
Unknown boot partition file system!
开头的(扇区3)。
所以这些字节序列创建了一些随机指令,而这没有任何内容
与程序有关。我以“X”开始这个部分,然后是jmp label
。
mov si, buffer
,cmp byte [si + 0x8000], 0x00
。我假设这是第二个代码的位置
引导加载程序应该是。 si = 0x7c93
+ 0x8000
= 0xfc93
。 [0xfc93] = 0x00
。
我不知道,也许这应该是 cmp byte [0x8000], 0x??
因为我们加载扇区
到0x8000
??我在第 3 扇区的开头插入了 X
,如果字节 0x8000
与 X
不同
这意味着这不是第二个引导加载程序。
我一步一步地浏览了代码,我注意到扇区 3 中的标签到目前为止已经有 +512 字节了 我将
org 0x8000
更改为org 0x7e00
。现在标签的偏移量已正确计算。
在
search_file:
中,我比较 10 个字节而不是 11 个字节,因为 0
将与 eb
进行比较,当然
这将是错误的。嗯,错误也很好,因为这样我就知道消息是正确生成的。 ;)
未显示错误消息,因为
print proc
位于未加载到内存的扇区2中。
我切换到第一个文件,并决定立即加载所有扇区。我内存中有内核和第二个引导程序。
如果找不到
kernel_filename
,程序会打印kernel_not_found_message
,否则我们有代码
它还假设加载另一个扇区(8),这当然是不可用的。
es = 0
,bx = 0
,dl = 0
。从 fdd 读取到 IVT。这会产生错误ah = 20h
,
文件共享违规。该程序返回后,我们有jmp 0x1000:0000
。跳到虚无...
我假设扇区 2 是内核,所以我跳转到
0:800a
。
好的,程序打印
starting_message
,接下来我们读取了生成的扇区例程
missing_pit
,分区表错误!,ah = 1
,无效的功能号。 buffer db 16 dup(21)
是
16字节,读扇区例程读取512字节。
我做了一些修改以使这段代码正常工作。 我在 qemu 中运行的图像文件是 3 个文件的组合。
bootloader1.bin
(第 1 区)
bootloader2.bin
(扇区 2,3,4,5,6)
activepartition.bin
(第 7 区)
; bootloader1.bin
ORG 0x7c00
BITS 16
start:
mov ah, 0x00 ; text mode
mov al, 0x03
int 0x10
xor ax, ax ; set up segments
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7c00
mov si, message ; "Bootloader - stage 1"
call print
mov ah, 2 ; load sector 2 - bootloader stage 2
mov al, 5
mov dh, 0
mov dl, 0x80
mov bx, 0x8000
mov cx, 0x0002
int 0x13
jc disk_error
mov si, stage2_bl_kernel
call print
mov si, 0x8000 ; offset of kernel code
cmp byte [0x8200], 'X' ; check if this is correct bootloader - stage 2 sector
jnz secondary_bootloader_missing
jmp 0x0000:0x8201
disk_error:
mov si, disk_error_message
call print
secondary_bootloader_missing:
mov si, secondary_bootloader_missing_message
call print
cli
hlt
print:
mov bx, 0
loop:
lodsb
cmp al, 0
je done
call _print
jmp loop
done:
ret
_print:
mov ah, 0x0E
int 0x10
ret
message:
db "Sector 1 (Bootloader - stage 1) - loaded!", 0x0A, 0x0D, 0
disk_error_message:
db "Disk error!", 0x0A, 0
secondary_bootloader_missing_message:
db "Sector 3 (Bootloader - stage 2)", 0x0A, 0x0D
db "Wrong sector - system halted!", 0x0A, 0x0D
stage2_bl_kernel:
db "Sector 2 (Kernel) - loaded!", 0x0A,0x0D
db "Sector 3 (Bootloader - stage 2) - loaded!", 0x0A,0x0D,0
buffer:
times 510-($ - $$) db 0
dw 0xAA55
; bootloader2.bin
ORG 0x8000
BITS 16
section .data
buffer db 512 dup('x')
pit_info db 16 dup('z')
active_partition_info dw 0x7878
section .text
global start
; sector 2
db "KERNEL.BIN"
start:
;mov ah, 0x00
;mov al, 0x03
;int 0x10
mov si, buffer + 508
mov di, active_id
mov cx, 4
repe cmpsb
jnz not_act_partition
mov si, correct_id
call print
mov si, partition_table_entries
call print
; check partition table entries
mov cx, 3
mov al, 0x31
mov bx, entry_num
mov ah, [bx]
mov si, buffer + 450
xor dx, dx ; if 0 there is no system
pt_entries:
push si
push ax
push bx
cmp al, [si]
jz good_sys
jb other_sys
mov si, entry_msg
call print
mov si, entry_num
call print
mov si, entry_msg_empty
call print
jmp entry_info_done
good_sys:
mov dx, si
mov si, entry_msg
call print
mov si, entry_num
call print
mov si, entry_msg_sys
call print
jmp entry_info_done
other_sys:
mov si, entry_msg
call print
mov si, entry_num
call print
mov si, entry_msg_other_sys
call print
jmp entry_info_done
entry_info_done:
pop bx
pop ax
add ah, 1
mov [bx], ah
pop si
add si, 16
dec cx
jnz pt_entries
cmp dx, 0
jz no_entry_info
mov si, entry_found
call print
found_bootable:
sub dx, 2 ; copy entry to pit_info
mov si, dx
mov di, pit_info
mov cx, 16
rep movsb
mov ax, 0x4b4f
mov [active_partition_info], ax
mov si, starting_message
call print
cli
system_stop:
hlt
jmp system_stop
no_entry_info:
mov si, no_entry_info_message
call print
cli
hlt
not_act_partition:
mov si, not_act_partition_message
call print
cli
hlt
error_missing_pit:
mov si, missing_pit
mov ax, 0x0000
mov ds, ax
call print
cli
hlt
no_bootable:
mov si, no_partition
mov ax, 0x0000
mov ds, ax
call print
cli
hlt
starting_message:
db "Starting the operating system...", 0x0A, 0
not_act_partition_message:
db "Sector 5 (Active partition)", 0x0A,0x0D
db "Incorrect Signature - system halted!", 0x0A,0x0D, 0
missing_pit:
db "Partition Table error!", 0x0A, 0
print:
mov bx, 0
call print_loop
ret
print_loop:
mov al, [si]
cmp al, 0
je print_done
mov ah, 0x0E
int 0x10
inc si
jmp print_loop
print_done:
ret
kernel_load:
mov ax, [active_partition_info]
add ax, 19
mov es, ax
mov bx, 0
mov ah, 0x02
mov al, 1
mov ch, 0
mov dh, 0
mov dl, 0x80
mov si, boot_sector_buffer
int 0x13
;mov si, file_system_signature
mov cx, 3
repe cmpsb
jnz not_fat12
jmp search_file
not_fat12:
mov si, file_system_error_message
call print
cli
hlt
boot_sector_buffer:
times 512 - ($ - $$) db 0
;-------- sector 3
sector3_start:
db "X" ; this is marker of 2nd bootloader
jmp search_file
file_system_error_message:
db "Unknown boot partition file system!", 0
search_file:
mov cx, 10
mov di, kernel_filename
rep cmpsb
je kernel_found
add bx, 32
cmp bx, 512
jae file_not_found
jmp search_file
kernel_found:
mov si, kernel_found_message
call print
load_partition:
mov ah, 0x02
mov al, 0x01
mov ch, 0x00
mov cl, 0x07
mov dh, 0x00
mov dl, 0x80
mov bx, buffer
int 0x13
jc load_failed
mov si, act_part_loaded
call print
jmp 0x0000:0x800a
file_not_found:
mov si, kernel_not_found_message
call print
cli
hlt
load_failed:
mov si, load_failed_message
call print
cli
hlt
kernel_filename:
db "KERNEL.BIN", 0
active_id:
db 0x41, 0x63, 0x74, 0x50
kernel_not_found_message:
db "Sector 2 (Kernel)",0x0A,0x0D
db "Wrong sector - system halted!", 0x0A, 0x0D,0
kernel_found_message:
db "Sector 2 (Kernel) - correct sector!", 0x0A,0x0D, 0
load_failed_message:
db "Sector 5 (Active partition)", 0x0A,0x0D
db "Disk error!", 0x0A,0x0D, 0
act_part_loaded:
db "Sector 5 (Active partition) - loaded!", 0x0A,0x0D,0
correct_id:
db "Sector 5 (Active partition) - correct signature!", 0x0A,0x0D,0
partition_table_entries:
db "Partition Table entries:", 0x0A,0x0D, 0
no_entry_info_message:
db "Sector 5 (Active partition)", 0x0A,0x0D
db "Partition Table - All entries are incorrect!", 0x0A,0x0D, 0
entry_msg:
db "Entry ",0
entry_msg_empty:
db " - Free slot.",0x0A,0x0D,0
entry_msg_other_sys:
db " - Other system",0x0A,0x0D,0
entry_msg_sys:
db " - Good system <3",0x0A,0x0D,0
entry_found:
db "Entry found!",0x0A,0x0D,0
entry_num:
db 0x31,0x00
no_partition:
db "Kernel partition cannot be found - does it have the active flag?", 0x0A, 0
;times 308 db 33
;boot_sector_buffer1:
times 1022 - ($ - sector3_start) db 0x00
; activepartition.bin
ORG 0x8c00
BITS 16
start:
mov si, actpart
call print
cli
hlt
print:
mov bx, 0
loop:
lodsb
cmp al, 0
je done
call _print
jmp loop
done:
ret
_print:
mov ah, 0x0E
int 0x10
ret
actpart:
db "Active Partition loaded!", 0x0A, 0x0D, 0
times 448-($ - $$) db 0
; PT0 - Empty entry
; PT1 - System
; PT2 - Other system
db 'P','T','0','D','r','v',0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
db 'P','T','2','D','r','v',0x80,'O','t','h','e','r',' ','s','y','s'
db 'P','T','1','D','r','v',0x80,'D','r','v','P','a','r','a','m','s'
times 12 db 0
dw 0x6341,0x5074 ; 7PAc
; makefile
BUILD_DIR = build
SRC_DIR = src
IMG_NAME = dev
dev: bl1 bl2 ap image
C:\Program Files\qemu\qemu-system-i386 -hda $(BUILD_DIR)\$(IMG_NAME).img
image: $(BUILD_DIR)\bootloader1.bin $(BUILD_DIR)\bootloader2.bin
@dd if=$(BUILD_DIR)\bootloader1.bin of=$(BUILD_DIR)\$(IMG_NAME).img bs=512
@dd if=$(BUILD_DIR)\bootloader2.bin of=$(BUILD_DIR)\$(IMG_NAME).img bs=512 seek=1
@dd if=$(BUILD_DIR)\activepartition.bin of=$(BUILD_DIR)\$(IMG_NAME).img bs=512 seek=6
@objdump -b binary -m i8086 -M intel -D $(BUILD_DIR)\$(IMG_NAME).img
@hexdump -C $(BUILD_DIR)\$(IMG_NAME).img
clean:
rm -f $(BUILD_DIR)\bootloader1.bin $(BUILD_DIR)\bootloader2.bin
bl1:
nasm -g -fbin $(SRC_DIR)\bootloader1.asm -o $(BUILD_DIR)\bootloader1.bin
bl2:
nasm -g -fbin $(SRC_DIR)\bootloader2.asm -o $(BUILD_DIR)\bootloader2.bin
ap:
nasm -g -fbin $(SRC_DIR)\activepartition.asm -o
$(BUILD_DIR)\activepartition.bin