【问题标题】:Why do boot loaders relocate in memory?为什么引导加载程序在内存中重定位?
【发布时间】:2009-07-29 21:17:52
【问题描述】:

我正在编写一个引导加载程序,我已经记录了大部分细节,但我不确定为什么有些引导加载程序在开始执行大部分操作之前会将自己重新定位到内存中。

谁能解释一下?

这种行为的一个例子是original v0.01 Linux kernel bootloader,其中包含以下注释:

boot.s 由 bios-startup 例程在 0x7c00 加载,并将自身移至地址 0x90000,然后跳转到那里。

【问题讨论】:

    标签: assembly system bootloader bios


    【解决方案1】:

    CookieOfFortune 基本上是正确的(因为他想将某些东西移到初始引导加载程序所在的位置),但它不是针对第二个引导加载程序,而是内核本身。

    来自他的cmets:

    然后它在 0x10000 加载系统, 使用 BIOS 中断。此后它 禁用所有中断,移动 系统下降到 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)
    

    【讨论】:

      【解决方案2】:

      来自链接的文章:

      实际上,MBR 通常包含一个引导加载程序,其目的是加载另一个引导加载程序 - 可以在其中一个分区的开头找到。这通常是一个非常简单的程序,它找到第一个标记为活动的分区,将其第一个扇区加载到 RAM 中,然后开始执行。由于按照惯例,新的引导加载程序也会加载到地址 7C00h,因此旧加载程序可能需要在执行此操作之前将其自身的全部或部分重新定位到不同的位置。另外,ES:SI 应该包含分区表在 RAM 中的地址,DL 是引导驱动器号。违反此类约定可能会导致引导加载程序与其他引导加载程序不兼容。

      【讨论】:

      • 但他特别询问了该页面底部的 Linux v0.01 引导加载程序,它不是似乎是一个 2 阶段加载程序。正如顶部状态的注释,它似乎将内核直接加载到 0x10000。
      • 谢谢,完美的答案!我已经知道这些应用程序是链接在一起的,但我没有想到所有其他应用程序也会加载到同一个地址。我注意到 DL 寄存器用于识别驱动器号,但我再次找不到任何关于此的明确文档。我认为互联网上没有标准的 BIOS 参考手册文档吗?我曾经有一本包含中断表的书,但它至少有 20 年的历史了,而且可能已经过时(并且丢失了)。
      • 这里是 BIOS 中断列表:en.wikipedia.org/wiki/BIOS_interrupt_call。这些显然仅在您的操作系统设置中断表之前可用。
      【解决方案3】:

      有时引导加载程序位于 ROM 中,需要在某个时候复制到 RAM。

      【讨论】:

      • 我使用了一个从 ROM 开始的引导加载程序。对不起。 =)
      • 好吧,好吧,通常不是:)
      猜你喜欢
      • 1970-01-01
      • 2018-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-31
      • 1970-01-01
      • 2011-03-29
      • 2015-06-02
      相关资源
      最近更新 更多