【问题标题】:Default registers and segments value on booting x86 machine引导 x86 机器时的默认寄存器和段值
【发布时间】:2017-09-07 15:09:36
【问题描述】:

我发现程序员通常会在他们的引导加载程序的第一行修复寄存器(有时是段),他们通常建议养成这个习惯。例如:

inc cx
dec bx
inc bp
dec di
xor ax, ax

我知道的是:BIOS 在引导过程中清除所有寄存器

在引导加载程序中初始化寄存器和段是一个好习惯吗?为什么?什么是默认寄存器、段和指针值(可能取决于芯片组)?

【问题讨论】:

  • 英特尔文档确实指定了 CPU 上电时每个寄存器包含的值。但是您是在询问 BIOS 移交给引导加载程序后的状态,所以谁知道...
  • 谢谢@Nayuki。你是对的。
  • 当您执行引导加载程序时,您只能假设一件事(除了一些 1980 年代不太兼容的计算机)。也就是说,由 BIOS 引导的驱动器 lnumber 位于 DL 寄存器中,除此之外,您不应假设标志的状态、段寄存器的状态和任何通用寄存器的状态.
  • 谢谢@MichaelPetch。总是有帮助的。
  • @MichaelPetch,IMO,这应该是一个答案。

标签: assembly memory-management x86-16 bootloader bios


【解决方案1】:

由于您提到了段寄存器的设置并且您的代码似乎是 16 位代码,我假设您讨论的是旧版 IBM-PC 引导加载程序 (PC-BIOS) 而不是 (EFI/UEFI)。在已制造的大多数设备的旧版引导加载程序中,您可以假设的很少。

当 PC-BIOS 从可用的引导设备加载引导扇区并将控制权转移给它时,所有寄存器的状态,但一个具有可用值。除了 80 年代和 90 年代的一些非标准(并且不是 100% 兼容的 BIOS)之外,寄存器 DL 将包含引导 BIOS 的引导驱动器号。这个值也是用来调用Int 13h disk service routines的值。

SS:SP 可能指向 RAM 中的某个位置,但不同的 BIOS 不同。应该设置自己的堆栈指针(SSSP),尤其是如果您打算将数据加载到内存中。除非您自己专门设置,否则您可能会无意中用数据覆盖堆栈。

有些人认为,当控制权转移到您的引导加载程序(通常通过 FAR JMP em>)。不幸的是,这不能保证。一些引导加载程序已知使用 0x07c0:0x0000,它也指向物理地址 0x07c00 (0x07c0segment:offset addressing 可以代表相同的物理地址(如 0x07c00)。我写了一个Stackoverflow question/answer,它记录了假设 CS 始终为 0x0000 的情况,这可能会导致一些有趣的错误,具体取决于环境。

不应将用于字符串指令(如CMPSMOVS)的方向标志(FLAGS 寄存器中的DF)假定为特定方向。大多数代码使用向前移动 (DF=0),但不能保证这是 BIOS 在跳转到引导加载程序之前将其设置为的方向。因此,应该使用CLD 明确清除它以向前移动,或使用STD 将其设置为向后移动。

除了前面提到的 DL 寄存器之外,您不应该假设任何通用寄存器都已初始化。我经常看到假定它们为零的引导加载程序。几乎从来没有这种情况。

我的 Stackoverflow General Bootloader Tips 中讨论了其中许多内容。

【讨论】:

    猜你喜欢
    • 2012-02-17
    • 2014-02-04
    • 2016-12-15
    • 2019-01-02
    • 2019-03-05
    • 2022-01-13
    • 1970-01-01
    • 2017-04-23
    相关资源
    最近更新 更多