Assembly 与设置段寄存器混淆

Assembly 与设置段寄存器混淆,assembly,x86,boot,bootloader,bios,Assembly,X86,Boot,Bootloader,Bios,我正在编写一个引导加载程序,下面的教程提供了以下代码: main: ;---------------------------------------------------- ; code located at 0000:7C00, adjust segment registers ;---------------------------------------------------- cli ; disable interru

我正在编写一个引导加载程序,下面的教程提供了以下代码:

main:

 ;----------------------------------------------------
 ; code located at 0000:7C00, adjust segment registers
 ;----------------------------------------------------

      cli                       ; disable interrupts
      mov     ax, 0x07C0                ; setup registers to point to our segment
      mov     ds, ax
      mov     es, ax
      mov     fs, ax
      mov     gs, ax

 ;----------------------------------------------------
 ; create stack
 ;----------------------------------------------------

      mov     ax, 0x0000                ; set the stack
      mov     ss, ax
      mov     sp, 0xFFFF
      sti                       ; restore interrupts

我可能有点误解,但如果SS寄存器包含0x0000,这不意味着ds、es、fs和gs会重叠堆栈吗?fs和gs寄存器的功能是什么?此外,cs段是否由BIOS自动设置?因为上面说代码是0000:7c00。此外,本教程从未讨论过中断被禁用的原因。我在某个地方读到,为了避免死锁,通常会禁用中断。这意味着什么?为什么会发生?

至少在理论上,是的,堆栈和代码可能重叠。它们不这样做的原因很简单:引导加载程序非常小,通常不会占用太多的堆栈空间,因此堆栈永远不会向下扩展到足以覆盖引导加载程序代码的末尾

就fs和gs而言,它们实际上没有任何专用用途。如果不看所讨论的引导加载程序的代码,那么它们是否被使用就成了问题。如果它们被使用的话,还有更多的问题要问它们会被用来做什么

磁盘BIOS将一个扇区从磁盘加载到07c00:0000h中,并跳转到该扇区。跳远设置
cs


设置堆栈时禁用中断,因为执行中断(试图)将数据推送到堆栈上。如果您尚未设置堆栈(SS和SP),您通常甚至不知道数据(标志和返回地址)可能会在内存中的何处结束,或者可能会覆盖哪些其他数据。这通常是不可取的,因此您至少要禁用中断,直到SS和SP都设置好。

除了古老的buggy 8088处理器(有些存在)之外,在指令期间更新任何段寄存器时,中断标志(暂时)关闭,直到下一条指令结束。如果您更新SS,然后在更新之后立即使用更新SP的指令,则在这两个过程中中断都将关闭。在286(及更高版本)中,唯一暂时关闭中断标志的寄存器是SS寄存器。由于可能会遇到有缺陷的8088处理器,通常建议显式关闭中断。您说过磁盘BIOS会将一个扇区从磁盘加载到07c00:0000h。我假设这是一个输入错误,应该是07c0:0000h或0000:7c00(或任何等效的)。如果您不编写与位置无关的代码(即,您执行非远绝对JMP和调用),您就不能假定BIOS跳转到您的代码设置正确的映射到同一物理地址的
CS
(因为有许多段:偏移量的组合)。如果您的代码不是位置独立的,那么可以在代码设置CS中对标签进行适当的远JMP。8086/8088/80286没有
FS
GS
段寄存器。这可能是故意的,但我只想指出一点。