BIOS中的引导序列会将它找到的第一个有效MBR加载到地址0x7C00的计算机物理内存中。
启动过程中SP应该使用哪个值?
org 7c00h ; set location counter.
mov ax, XXX ; What is XXX?
mov sp, ax
; Now PUSH an POP are safe
答案 0 :(得分:4)
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启动MBR与07C0:0000,所以jmp确保CS = 0
答案 1 :(得分:3)
SS:SP
的任何值,以便为代码 AND 中断服务例程提供足够的堆栈空间是可以的。
当然,您的堆栈不应与任何代码或其他数据冲突,也不应碰到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
和SP
时,您必须禁用中断或首先更改SS
,然后在紧随其后更改SP
指令(如上所示)。
或者您可以使用LSS SP, ...
指令,但它将远地址的地址作为参数,这意味着您的新SS:SP
值首先需要位于内存中的某个位置。
另一种更改SS
和SP
的方法是使用PUSH
和RETF
。