本文介绍了引导x86机器时的默认寄存器和段值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现通常程序员会在启动加载程序的第一行中对寄存器(有时是段)进行修正,并且他们通常建议养成这种习惯.例如:

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

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

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

解决方案

由于您提到了段寄存器的设置,并且您的代码似乎是16位代码,因此我假设您正在讨论旧的IBM-PC引导加载程序(PC-BIOS)而不是(EFI/UEFI).对于大多数已制造的设备,传统的引导加载程序几乎没有什么可以假设的.

当PC-BIOS从可用的引导设备加载引导扇区并将所有寄存器的状态转移到该引导扇区时,只有一个寄存器具有可用值.除了80年代和90年代的一些非标准(不是100%兼容的BIOS)之外,寄存器 DL 将包含BIOS引导的引导驱动器号.此值也是用于调用 Int 13h磁盘服务例程的值.

SS:SP 可能指向RAM中的某个位置,但该位置因BIOS而异.应该设置自己的堆栈指针( SS SP ),尤其是当您打算将数据加载到内存中时.除非您专门进行设置,否则您可能会无意间用数据覆盖堆栈.

有人认为,将控制权转移到引导加载程序(通常是通过 FAR JMP 时, CS:IP 始终设置为0x0000:0x7c00(CS = 0x0000,IP = 0x7c00)) em>).不幸的是,这不能保证.已知一些引导加载程序使用0x07c0:0x0000,它也指向物理地址0x07c00(0x07c0< segment:offset寻址可以表示相同的物理地址(例如0x07c00 ).我写了一个 Stackoverflow问题/答案捕获了假设 CS 始终为0x0000的情况,这可能会导致一些有趣的错误,具体取决于环境.

用于字符串指令的方向标记(FLAGS寄存器中的DF)(例如 CMPS MOVS )不应被认为是一个特定的方向.大多数代码使用向前移动(DF = 0),但不能保证这是BIOS跳转到引导加载程序之前所设置的方向.因此,应该使用 CLD 明确清除它以进行转发移动或使用 STD 进行设置.. >

除上述 DL 寄存器外,您不应假定所有通用寄存器都已初始化.我经常看到引导加载程序假定它们为零.几乎从来没有这样.

其中许多内容在我的Stackoverflow 常规Bootloader提示中进行了讨论.

I found that usually programmers fixup registers (and sometimes segments) on their very first lines of bootloaders and they advice usually to have this habit. For instance:

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

What I know is that: BIOS clears all registers during the boot procedure!

Is it a good habit to initialize registers and segments in a bootloader? Why? What are the default registers, segments and pointers value (Maybe chipset dependent)?

解决方案

Since you mention settings of segment registers and your code appears to be 16-bit code I will assume you are discussing legacy IBM-PC bootloaders (PC-BIOS) and not (EFI/UEFI). In legacy bootloaders for the majority of equipment that has been manufactured there is very little you can assume.

By the time the PC-BIOS loads the boot sector from an available boot device and transfer control to it the state of all the registers but one have a usable value. With the exception of some non-standard (and not 100% compatible BIOSes) from the 80s and 90s the register DL will contain the boot drive number the BIOS booted from. This value is also the one used to call Int 13h disk service routines.

SS:SP likely points to somewhere in RAM but where that is differs from BIOS to BIOS. One should setup their own stack pointer (SS and SP) especially if you intend to load data into memory. You could unintentionally overwrite the stack with data unless you specifically set it yourself.

Some argue that CS:IP are always set to 0x0000:0x7c00 (CS=0x0000, IP=0x7c00) when control is transferred to your bootloader (usually through a FAR JMP). Unfortunately this isn't guaranteed. Some bootloaders are known to use 0x07c0:0x0000 which also points to physical address 0x07c00 (0x07c0<<4+0x0000). This is because different segment:offset addressing can represent the same physical address (like 0x07c00). I wrote a Stackoverflow question/answer that captures a situation where assuming CS is always 0x0000 can lead to some interesting bugs depending on the environment.

The direction flag (DF in FLAGS register) used for the string instructions (like CMPS and MOVS) should not be assumed to be a particular direction. Most code uses forward movement (DF=0) but there is no guarantee that is the direction the BIOS set it to before jumping to the bootloader. Because of that one should explicitly clear it with CLD for forward movement or set it with STD for backward movement.

Besides the aforementioned DL register you should not assume any of the general purpose registers are initialized at all. Often I see bootloaders that assume they are zero. This is almost never the case.

Many of these things are discussed in my Stackoverflow General Bootloader Tips.

这篇关于引导x86机器时的默认寄存器和段值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-19 16:23