2012-05-07 47 views
3

我在写一个引导加载程序和我下面教程工作提供此代码:与建立分部困惑寄存器

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寄存器的功能?另外,是由BIOS自动设置的cs段吗?因为它说代码位于0000:7c00。另外,本教程永远不会解释为什么中断被禁用。我在某处读到中断通常是禁用的,以避免死锁。这是什么意思,为什么会发生?

+0

只是一个观察:你的代码只能在386和更高的处理器上工作。 8086/8088/80286没有'FS'和'GS'段寄存器。这可能是由设计,但我只是想指出。 –

回答

8

至少在理论上,是的,堆栈和代码可能会重叠。他们不这么做的原因很简单:引导加载程序非常小,通常不会使用太多堆栈空间,所以堆栈永远不会增长太多以覆盖引导加载程序代码的末尾。

就fs和gs而言,它们并没有真正的用途。如果不考虑引导加载程序的代码,可能会有人质疑它们是否被使用。如果他们被使用,它仍然有更多的问题,他们会用什么

磁盘BIOS从磁盘加载一个扇区到07c00:0000h,并远远地跳到它。远跳集合cs

您在设置堆栈时禁用中断,因为执行中断(尝试)将数据推入堆栈。如果尚未设置堆栈(包括SS和SP),通常甚至不知道数据(标记和返回地址)可能最终在内存中的什么位置,或者可能覆盖哪些其他数据。这通常是不可取的,因此至少在SS和SP都被设置之前,禁用中断。

+0

除了古老的8088处理器(某些存在)之外,在指令持续期间更新ANY段寄存器期间,中断标志被关闭(临时),直到* following *指令结束。如果更新了SS,然后按照一条更新SP的指令进行操作,那么中断将在两者之间关闭。从286(及更高版本)开始,只有暂时关闭中断标志的寄存器才是SS寄存器。 –

+0

由于遇到错误8088处理器的可能性,通常建议明确关闭中断。 –

+0

你说_磁盘BIOS从磁盘加载一个扇区到07c00:0000h_。我认为这是一个错字,应该是_07c0:0000h_或_0000:7c00_(或任何等效的东西)。如果您不写位置独立代码(即执行非远程绝对JMP和CALL),则不能假定BIOS跳转到设置正确的“CS”的代码(因为存在许多segment:offset组合)映射到相同的物理地址。如果你的代码不是位置独立的,那么可以适当地在代码设置CS中对FAR JMP执行一个标签。 –