BIOS 中的引导程序会将它找到的第一个有效 MBR 加载到地址 0x7C00 处的计算机物理内存中。
引导过程中的 SP 应该使用哪个值?
org 7c00h ; set location counter.
mov ax, XXX ; What is XXX?
mov sp, ax
; Now PUSH an POP are safe
BIOS 中的引导程序会将它找到的第一个有效 MBR 加载到地址 0x7C00 处的计算机物理内存中。
引导过程中的 SP 应该使用哪个值?
org 7c00h ; set location counter.
mov ax, XXX ; What is XXX?
mov sp, ax
; Now PUSH an POP are safe
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
任何值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 字节的空间。这是足够的堆栈空间。
另请注意,当同时更改SS
and时SP
,您要么必须在禁用中断的情况下执行此操作,要么先更改SS
然后SP
在紧随其后的指令中更改(如上所示)。
或者,您可以使用该LSS SP, ...
指令,但它将远地址的地址作为参数,这意味着您的新SS:SP
值首先需要位于内存中的某个位置。
SS
改变and的另一种方法SP
是使用PUSH
and RETF
。