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 推送 FLAGS
、CS
和 IP
。
ISR 然后可能并且通常确实需要更多堆栈。
堆栈背后的基本假设是 SS:SP
以下的所有内容都被认为是空闲的、可用的内存。
当您将 SP
设置为 7cfeh 时,您只是说 7cfeh 下面的每个内存位置都可以免费供其他人用作堆栈内存其他。
这就是你看到的垃圾。
请注意,列为 200、220 和 240 的地址在 下方 堆栈指针,在我看来,对此类地址使用 "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
我正在使用 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 推送 FLAGS
、CS
和 IP
。
ISR 然后可能并且通常确实需要更多堆栈。
堆栈背后的基本假设是 SS:SP
以下的所有内容都被认为是空闲的、可用的内存。
当您将 SP
设置为 7cfeh 时,您只是说 7cfeh 下面的每个内存位置都可以免费供其他人用作堆栈内存其他。
这就是你看到的垃圾。
请注意,列为 200、220 和 240 的地址在 下方 堆栈指针,在我看来,对此类地址使用 "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