引导加载程序堆栈配置

3
以下是教育实模式x86操作系统MikeOs的代码开头(mikeos.sourceforge.net)。据我所知,x86堆栈向“下”增长,即向低内存增长,并且堆栈段寄存器ss指向栈段中最低可能的内存位置(偏移量为0)。因此,问题是,为什么需要在代码段中添加4096字节才能创建4K堆栈?是否只需在代码段中添加512字节并将其存储在ss堆栈段中即可满足要求,因为引导扇区可能仅长512字节?
 BITS 16

 start:
  mov ax, 07C0h   ; Set up 4K stack space after this bootloader
  add ax, 288     ; (4096 + 512) / 16 bytes per paragraph
  mov ss, ax
  mov sp, 4096
  mov ax, 07C0h   ; Set data segment to where we're loaded
  mov ds, ax

你的意思是将 sp 初始化为0,然后将堆栈段向前移动吗?考虑一下当您尝试将某些内容推送到堆栈上时会发生什么。假设您正在推送一个字:sp 减2, 并且会回绕到 0xFFFE。假设 ss == 1。将要写入的地址将是 (1 * 0x10) + 0xFFFE == 0x1000E,而不是 (1 * 0x10) - 2 == 0x0E - Michael
不,我的意思只是执行mov ax, 07C0h add ax, 32 mov ss, ax mov sp, 4096。据我所知,这将在512字节的引导扇区之后创建一个4K堆栈。 - user3793475
1
注意 - Microsoft的MSDOS和Windows 98的分区扇区代码将所有段寄存器设置为零,然后将SP设置为7c00h(加载的映像正下方)。然后,代码将自身移动到0000h:0600h,并从0000h:0600h的某个偏移处跳转以继续执行。一旦到达0000h:0600h,代码会查找引导扇区,在0000h:7c00h处加载它,并继续该过程。在多重引导系统上,此循环可能会再次重复。 - rcgldr
3个回答

2

这里是内存映射表,以便更容易进行分析:

-------------- <— 07C0:0 boot loader memory starts
|            |
| 512 bytes  |  For the boot loader code
--------------
|            |  It could be use for whatever purpose the author has planned
|            |  for this memory area.
| 4096 + 512 |  (Maybe for the OS? Or stage2 loader? Who knows, it doesn't matter.)
|            |
-------------- <- 19C0:0 - Stack Segment(SS):Stack Pointer(SP) - Max of the stack
|            |        /\
| 4KB stack  |        || Stack grows
--------------    19C0:1000                               - Start of the stack(bottom)

我之前在另一个答案下检查过这段代码,但是栈下面的4k似乎被用作磁盘缓冲区。 - Michael Petch

1

栈的大小与使用栈的代码大小无关。例如:递归代码可能只有几十个字节,但使用的栈却可能达到几兆字节 - 尽管在引导程序中很少出现递归。然而,存在中断和ROM中的固件,它们可能作为某些中断的结果获得控制权 - 这不需要太多的栈空间,但会增加引导程序所需的空间。总的来说,我认为512字节的栈足够了,但最好保险起见,特别是如果提供更多的栈空间成本为零。


0

你说得对。

没有理由将4096添加到ss中。512就足够了(只是为了在代码后移动)。也许作者为某些数据保留了这4k字节?


好的,我明白了。但是让人困惑的是作者将恰好4K添加到堆栈段,并设置了一个4K堆栈。也许这只是巧合。 - user3793475
很难说真正的原因是什么 :). 如果您知道您的代码不会很大并且不会使用太多堆栈,那么ss=cs也很常见 ;) 同样,ds、es、fs和gs = cs也可能发生。这允许您使用其他段寄存器访问任何段中的任何数据。 - Michał Walenciak
@MichałWalenciak:如果您使用了微型(com)内存模型,则实际上这是默认设置。对于简单的汇编程序,这可以大大减少代码复杂性。 - PMF
4K堆栈是最糟糕的情况。在支持AHCI的系统上,int 13h可以使用那4k的大块空间。PCI BIOS规范指出,这些调用需要1k的空间。通常认为,在大多数情况下,4k堆栈足够使用。如果您知道不会使用BIOS调用,则可以使用更小的堆栈。至于原帖中的代码,不清楚他们为什么要以那种方式偏移堆栈。 - Michael Petch
仔细查看MikeOS代码后,引导加载程序和堆栈顶部(堆栈的最低内存地址)之间的额外4k内存用作磁盘缓冲区。 - Michael Petch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接