3

BIOS 中的引导程序会将它找到的第一个有效 MBR 加载到地址 0x7C00 处的计算机物理内存中。

引导过程中的 SP 应该使用哪个值?

org 7c00h      ; set location counter.
mov ax, XXX    ; What is XXX?
mov sp, ax
; Now PUSH an POP are safe
4

2 回答 2

4

0000:0500 到 0007:FFFF 保证免费使用。正确的初始化如下所示:

org 0x0600
...

cli
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7C00

; relocate itself
mov si, sp
mov di, 0x0600
mov cx, 256
rep movsw

; make sure we'are at 0000:0600+x
jmp 0:.reloc
.reloc:
push 2
popf    ; flags with all off

我使用 7C00,堆栈向下,代码向上。您可以将 7C00 替换为上述任何有效范围,只要确保不覆盖您自己的代码/数据。

顺便说一句,大多数 MBR 会按照传统将自身重新定位到 0000:0600,并将 VBR 链式加载到 7C00。

还要注意 jmp .reloc,一些有问题的 BIOS 以 07C0:0000 启动 MBR,所以那里的 jmp 确保 CS=0

于 2012-05-16T00:51:09.173 回答
3

任何值SS:SP只要有足够的堆栈空间供您的代码中断服务例程使用即可。

而且,当然,您的堆栈不应与您的任何代码或其他数据发生冲突,也不应运行到 ROM 或内存映射的设备地址范围内。

BIOS 不保证SS:SP您的引导扇区会收到什么。所以,只改变SP是不对的。

例如,您可以这样做(如果此位置没有您的任何代码或数据):

...
mov ax, 0
mov ss, ax
mov sp, ax
...

这将设置SS:SP为 0:0。不要惊慌。下一次推送将首先SP从 0 递减到 0xFFFE 并写入 0:0xFFFE,而不是 0:0。

这将在引导扇区的末尾和最大堆栈指针地址之间为您提供 0x10000 - (0x7c00 + 0x200) = 33280 字节的空间。这是足够的堆栈空间。

另请注意,当同时更改SSand时SP,您要么必须在禁用中断的情况下执行此操作,要么先更改SS然后SP在紧随其后的指令中更改(如上所示)。

或者,您可以使用该LSS SP, ...指令,但它将远地址的地址作为参数,这意味着您的新SS:SP值首先需要位于内存中的某个位置。

SS改变and的另一种方法SP是使用PUSHand RETF

于 2012-05-15T14:29:42.327 回答