我正在编写我的操作系统。一切似乎都进展顺利(甚至可能太多了)。问题是控制权在读取磁盘扇区后立即转移到引导加载程序的第二部分。这怎么可能?
boot1.asm
:
[bits 16]
[org 0x7c00]
jmp boot
BOOT2_OFFSET equ 0x1000
boot:
mov [BOOT_DRIVE], dl
mov bx, MSG_BOOT1
call print
call print_nl
call load_boot2
jmp $
load_boot2:
mov bx, MSG_BOOT2_LOAD
call print
call print_nl
mov bx, BOOT2_OFFSET
mov dh, 16
mov dl, [BOOT_DRIVE]
call disk_load
jmp $
%include "disk.asm"
%include "print.asm"
BOOT_DRIVE db 0
MSG_BOOT1 db "Loading in BOOT1...", 0
MSG_BOOT2_LOAD db "Loading BOOT2.bin...", 0
times 510 - ($ - $$) db 0
dw 0xaa55
disk.asm
:
; load 'dh' sectors from drive 'dl' into ES:BX
disk_load:
pusha
push dx
mov ah, 0x02
mov al, dh
mov cl, 0x02
mov ch, 0x00
mov dh, 0x00
int 0x13
jc disk_error
jnc disk_success
pop dx
cmp al, dh
jne sectors_error
popa
ret
disk_success:
mov bx, DISK_SUCCESS
call print
call print_nl
ret
disk_error:
mov bx, DISK_ERR
call print
call print_nl
jmp $
sectors_error:
mov bx, SECT_ERR
call print
jmp $
DISK_ERR: db "Disk read error!", 0
SECT_ERR: db "Incorrect number of sectors read!", 0
DISK_SUCCESS: db "Disk read success!", 0
print.asm
:
print:
pusha
start:
mov al, [bx]
cmp al, 0
je done
add bx, 1
jmp start
done:
popa
ret
print_nl:
pusha
mov ah, 0x0e
mov al, 0x0a
int 0x10
mov al, 0x0d
int 0x10
popa
ret
boot2.asm
[bits 16]
[org 0x1000]
jmp boot2
boot2:
mov bx, MSG_BOOT2
call print
call print_nl
jmp $
%include "print.asm"
MSG_BOOT2 db "Loading in BOOT2...", 0
- 结论
qemu
:
我是这样收集的:
nasm boot1.asm -f bin -o boot1.bin
nasm boot2.asm -f bin -o boot2.bin
cat boot1.bin boot2.bin > os.bin
qemu-system-i386 -fda os.bin
寄存器
disk_load
存储在堆栈中,并且dx
(为什么要dx
单独保存?):但在分支中,
disk_success
他们没有从那里得到:在这里,用
ret
'e 可以转换到之前在 中的地址,dx
这就是0x1000
(dh
=16
dl
=0
),这非常“方便”,因为 这与加载引导加载程序第二部分的地址相匹配...