assembly - 启动 x86 机器上的默认寄存器和段值

标签 assembly memory-management x86-16 bootloader bios

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

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 disk service routines 的值。 .

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

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

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

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

其中许多内容都在我的 Stackoverflow General Bootloader Tips 中进行了讨论。 .

关于assembly - 启动 x86 机器上的默认寄存器和段值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43359327/

相关文章:

c++ - 如何在 Visual Studio 汇编程序输出中分解名称?

c - 访问函数中的双指针结构

iphone - 数据 NSManagedObject 上的 valueForKey 不释放内存

assembly - IBM 5150 - int 21h 损坏段寄存器

assembly - 我如何获得负股息的正模

c++ - ASM 中的 float

assembly - 是否有更好的 AVX 指令来从 3 ymm 寄存器移动数据?

linux - 页缓存与 L1 缓存?

delphi - 为什么某些汇编指令没有记录在案

assembly 基础 : Output register value