16位实模式栈内存布局

Stack memory layout in 16 bit real mode

我正在使用 NASM 和 qemu 进行实模式裸机编程。我正在尝试了解堆栈的工作原理,尤其是它是如何存储在内存中的。

我的代码在一个 512 字节的引导扇区中,最后是 "magic byte" 0xaa55,它被加载到内存地址 0x7c00.

我已将堆栈基指针设置为 0x7cfe。我知道我必须注意不要用堆栈覆盖我的代码,但事实并非如此。我的代码只占用几个字节。这是我的代码:

[BITS 16]
org 0x7c00

mov bp, 0x7cfe
mov sp, bp

push 'A'

jmp $

times 510-($-$$) db 0
dw 0xaa55

程序设置堆栈指针,将字符'A'压入堆栈,然后开始无限循环。我 assemble 并使用以下命令调整它:

nasm -f bin boot.asm -o boot.bin
&& qemu-system-i386 -drive file=boot.bin,index=0,media=disk,format=raw -monitor stdio

当模拟器是运行时,我通过以下方式转储内存:

qemu> pmemsave 0x7c00 512 medump.bin

当我打开文件 memdump.bin 时,我在基地址和之前(如果我们认为在术语上,则在顶部)看到字符 'A'(41 00 因为是小端)堆栈)我看到很多 "junk",即:

200: 00 00 00 00 C5 EF 00 00 00 00 00 00 02 02 00 DF 00 00 FE F7
220: 00 00 FE 7C 00 00 BC 93 00 00 00 DF 00 00 60 F8 00 00 00 00
240: 00 00 55 AA 00 00 08 7C 00 00 02 02 41 00 00 00 00 00 00 00

那些字节是什么?

如果我不设置堆栈指针基址,代码之后和字节0xaa55之前的所有字节都是零。

你能提供任何信息或至少一些指示吗?

谢谢

为了处理中断,CPU 需要正确设置堆栈。
只是为了通过将控制传递给 ISR(中断服务路由)来服务中断,CPU 推送 FLAGSCSIP

ISR 然后可能并且通常确实需要更多堆栈。

堆栈背后的基本假设是 SS:SP 以下的所有内容都被认为是空闲的、可用的内存。
当您将 SP 设置为 7cfeh 时,您只是说 7cfeh 下面的每个内存位置都可以免费供其他人用作堆栈内存其他。
这就是你看到的垃圾。
请注意,列为 200220240 的地址在 下方 堆栈指针,在我看来,对此类地址使用 "on top",虽然比喻正确,但有点令人困惑。

如果您想确保成为唯一一个弄乱堆栈的人,请尽早发出 cli(绝对在设置堆栈之前)。
这在 UP 系统中就足够了。


编辑

不要假设 SS 为零,明确设置它,用

初始化堆栈
mov ax, <ss_value>

;cli                    Decomment for very old 8088 compatibility

;Use these instructions in this order in pair
;Interrupts are disabled for 1 inst after mov ss, ...
mov ss, ax
mov sp, <sp_value>

;sti                    Decomment for very old 8088 compatibility