如何从扇区加载应用程序?
How to load application from sectors?
我正在创建必须加载存储在接下来的 32 个扇区中的应用程序的自定义 MBR,除了加载应用程序外一切正常,我不明白我做错了什么,所以如果有人知道什么以及如何修复它,请帮助我。
org 0x7c00
bits 16
Kernel:
;---Setup Segments
xor ax, ax ;AX=0
mov ds, ax ;DS=ES=0 because we use an org of 0x7c00 - Segment<<4+offset = 0x0000<<4+0x7c00 = 0x07c00
mov es, ax
mov ss, ax
mov sp, 0x7c00 ;SS:SP= 0x0000:0x7c00 stack just below bootloader
;---Read Kernel
mov bx, buffer ;ES: BX must point to the buffer
mov [BOOT_DRIVE], dl ;save the boot drive
mov dl, [BOOT_DRIVE] ;use boot drive passed to bootloader by BIOS in DL
mov dh,0 ;head number
mov ch,0 ;track number
mov cl,2 ;sector number
mov al,128 ;number of sectors to read
mov ah,2 ;read function number
int 13h
;---Start Application
jmp buffer
;Fake MBR Signature
BOOT_DRIVE: db 0
times 510 - ($ - $$) db 0
dw 0xAA55
;Victoria Freeware - The Kernel
victoria: incbin "Victoria.com"
times 65536 - ($ - $$) db 0
;Buffer
buffer:
主要问题是,当您调用 int 0x13, ah = 0x02
时,您需要 dl
中要读取的设备的设备编号。您启动的设备编号由 BIOS 在 dl
中提供给您,但代码会覆盖它(之前的 mov dx, 0x184F
),因此您要求从一个完全不同的设备(可能不存在)。
还有多个其他问题。段寄存器设置不正确(例如 mov ax,ds
而不是 mov ds,ax
)并且没有设置在正确的位置(应该在使用段之前完成 - 例如在 ds
段被代码中的 mov al,[si]
指令用来打印一个字符串)。你不能只是假设 int 0x13, ah = 0x02
工作而不检查错误(如果有错误你应该显示 nice "end user readable" error message/s 让用户有希望弄清楚他们能做什么解决问题)。
最后还有一个概念问题。对于分区设备(硬盘驱动器、USB 闪存等),MBR 应该做的主要事情是从活动分区启动操作系统的引导加载程序(MBR 不应被视为任何特定操作系统的一部分,操作系统的引导代码开始与操作系统分区的第一个扇区)。对于未分区的设备(软盘),由于各种原因你需要一个 BPB(BIOS 参数块)(这样其他操作系统就不会认为磁盘未格式化,并且 BIOS 认为它对各种特殊情况有效,例如 "USB flash emulating floppy" 和 "bootable CD emulating floppy").
更新
是的,问题正在发生变化,上面的一些答案不再适用。目前的问题是:
ds
在被使用它的 mov [BOOT_DRIVE], dl
指令使用之前未设置
mov ax,cs
不可能是对的。当 BIOS 启动代码时,它可以执行 jmp 0x0000:0x7C00
或 jmp 0x07C0:0x0000
(或任何组合),因此 cs
未设置为已知值并将未知值加载到 ax
帮不上什么忙。
mov ax,ds
(紧接在 mov ax,cs
之后)没有设置 ds
,而是加载 ax
BIOS 碰巧留在 [=16= 中的值].我认为这条指令应该是 mov ds,ax
(可能有效也可能无效,具体取决于使用的是哪个 computer/BIOS)
mov ax, ds
、mov ax, es
、mov ax, ss
(紧跟在kernel:
标签之后)有同样的问题(应该是mov ds, ax
、mov es, ax
,以及 mov ss, ax
我正在创建必须加载存储在接下来的 32 个扇区中的应用程序的自定义 MBR,除了加载应用程序外一切正常,我不明白我做错了什么,所以如果有人知道什么以及如何修复它,请帮助我。
org 0x7c00
bits 16
Kernel:
;---Setup Segments
xor ax, ax ;AX=0
mov ds, ax ;DS=ES=0 because we use an org of 0x7c00 - Segment<<4+offset = 0x0000<<4+0x7c00 = 0x07c00
mov es, ax
mov ss, ax
mov sp, 0x7c00 ;SS:SP= 0x0000:0x7c00 stack just below bootloader
;---Read Kernel
mov bx, buffer ;ES: BX must point to the buffer
mov [BOOT_DRIVE], dl ;save the boot drive
mov dl, [BOOT_DRIVE] ;use boot drive passed to bootloader by BIOS in DL
mov dh,0 ;head number
mov ch,0 ;track number
mov cl,2 ;sector number
mov al,128 ;number of sectors to read
mov ah,2 ;read function number
int 13h
;---Start Application
jmp buffer
;Fake MBR Signature
BOOT_DRIVE: db 0
times 510 - ($ - $$) db 0
dw 0xAA55
;Victoria Freeware - The Kernel
victoria: incbin "Victoria.com"
times 65536 - ($ - $$) db 0
;Buffer
buffer:
主要问题是,当您调用 int 0x13, ah = 0x02
时,您需要 dl
中要读取的设备的设备编号。您启动的设备编号由 BIOS 在 dl
中提供给您,但代码会覆盖它(之前的 mov dx, 0x184F
),因此您要求从一个完全不同的设备(可能不存在)。
还有多个其他问题。段寄存器设置不正确(例如 mov ax,ds
而不是 mov ds,ax
)并且没有设置在正确的位置(应该在使用段之前完成 - 例如在 ds
段被代码中的 mov al,[si]
指令用来打印一个字符串)。你不能只是假设 int 0x13, ah = 0x02
工作而不检查错误(如果有错误你应该显示 nice "end user readable" error message/s 让用户有希望弄清楚他们能做什么解决问题)。
最后还有一个概念问题。对于分区设备(硬盘驱动器、USB 闪存等),MBR 应该做的主要事情是从活动分区启动操作系统的引导加载程序(MBR 不应被视为任何特定操作系统的一部分,操作系统的引导代码开始与操作系统分区的第一个扇区)。对于未分区的设备(软盘),由于各种原因你需要一个 BPB(BIOS 参数块)(这样其他操作系统就不会认为磁盘未格式化,并且 BIOS 认为它对各种特殊情况有效,例如 "USB flash emulating floppy" 和 "bootable CD emulating floppy").
更新
是的,问题正在发生变化,上面的一些答案不再适用。目前的问题是:
ds
在被使用它的mov [BOOT_DRIVE], dl
指令使用之前未设置mov ax,cs
不可能是对的。当 BIOS 启动代码时,它可以执行jmp 0x0000:0x7C00
或jmp 0x07C0:0x0000
(或任何组合),因此cs
未设置为已知值并将未知值加载到ax
帮不上什么忙。mov ax,ds
(紧接在mov ax,cs
之后)没有设置ds
,而是加载ax
BIOS 碰巧留在 [=16= 中的值].我认为这条指令应该是mov ds,ax
(可能有效也可能无效,具体取决于使用的是哪个 computer/BIOS)mov ax, ds
、mov ax, es
、mov ax, ss
(紧跟在kernel:
标签之后)有同样的问题(应该是mov ds, ax
、mov es, ax
,以及mov ss, ax