我正在编写一个引导加载程序,并且我已经记录了大部分细节,但我不确定为什么一些引导加载程序在开始执行大部分操作之前会将自己重新定位到内存中。
谁能解释一下?
这种行为的一个例子是原始的 v0.01 Linux 内核引导加载程序,其中包含以下注释:
boot.s 由 bios-startup 例程在 0x7c00 加载,并将自身移至地址 0x90000,然后跳转到那里。
我正在编写一个引导加载程序,并且我已经记录了大部分细节,但我不确定为什么一些引导加载程序在开始执行大部分操作之前会将自己重新定位到内存中。
谁能解释一下?
这种行为的一个例子是原始的 v0.01 Linux 内核引导加载程序,其中包含以下注释:
boot.s 由 bios-startup 例程在 0x7c00 加载,并将自身移至地址 0x90000,然后跳转到那里。
CookieOfFortune 本质上是正确的(因为他想将某些东西移动到初始引导加载程序所在的位置),但它不是用于第二个引导加载程序,而是用于内核本身。
从他的评论中:
然后它使用 BIOS 中断在 0x10000 处加载系统。此后它禁用所有中断,将系统移至 0x0000,更改为保护模式,并调用系统启动。然后系统必须在它自己的表中重新初始化保护模式,并根据需要启用中断。
他希望内核位于 0x0000...0xKERNEL_SIZE-1,但初始引导加载程序当前位于 0x7C00,因此如果内核超过约 32 KB,它将在移动引导加载程序时覆盖它。内核位于 0x0000 的事实也解释了此注释:
“注意!当前系统最多为 8*65536 字节长。”
如果它从 0 开始超过 512 KB,则可能会碰到 x86 地址空间的保留区域。
我相信这个代码部分包含实际跳转到内核
mov ax,#0x0001 | protected mode (PE) bit
lmsw ax | This is it!
jmpi 0,8 | jmp offset 0 of segment 8 (cs)
从链接的文章:
实际上,MBR 通常包含一个引导加载程序,其目的是加载另一个引导加载程序 - 可以在其中一个分区的开头找到。这通常是一个非常简单的程序,它找到第一个标记为活动的分区,将其第一个扇区加载到 RAM 中,然后开始执行。由于按照惯例,新的引导加载程序也会加载到地址 7C00h,因此旧加载程序可能需要在执行此操作之前将其全部或部分重新定位到不同的位置。此外,ES:SI 应该包含分区表在 RAM 中的地址,DL 是引导驱动器号。违反此类约定可能会导致引导加载程序与其他引导加载程序不兼容。
有时引导加载程序位于 ROM 中,并且需要在某个时候复制到 RAM。