Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 16位实模式下的堆栈内存布局_Assembly_X86_Real Mode - Fatal编程技术网

Assembly 16位实模式下的堆栈内存布局

Assembly 16位实模式下的堆栈内存布局,assembly,x86,real-mode,Assembly,X86,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

我正在使用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”推入堆栈,然后启动无限循环。我使用以下命令对其进行组装和tun:

nasm -f bin boot.asm -o boot.bin
&& qemu-system-i386 -drive file=boot.bin,index=0,media=disk,format=raw -monitor stdio
在emulator运行时,我按以下方式转储内存:

qemu> pmemsave 0x7c00 512 medump.bin
当我打开文件
memdump.bin
时,我在基址处看到字符“A”(
41 00
,因为它是小尾端),在此之前(如果我们从堆栈的角度考虑,它位于顶部),我看到很多“垃圾”,即:

这些字节是什么

如果我没有设置堆栈指针基数,则代码后面和字节之前的所有字节
0xaa55
都是零

你能提供一些信息或至少一些建议吗


谢谢

为了处理中断,CPU需要一个正确设置的堆栈。
仅为了通过向ISR(中断服务路由)传递控制来服务中断,CPU按下
标志
CS
IP

然后,ISR可能,而且通常需要更多的堆栈

堆栈背后的基本假设是
SS:SP
下面的所有内容都被认为是空闲的、可用的内存。
当您将
SP
设置为7cfeh时,您只是说7cfeh以下的每个内存位置都是空闲的,其他人可以将其用作堆栈内存。
这就是你看到的垃圾。
请注意,列为200、220和240的地址位于堆栈指针的下方,在我看来,对这些地址使用“在顶部”虽然在比喻上是正确的,但有点混乱

如果您想确保自己是唯一一个干扰堆栈的人,请尽早(绝对在设置堆栈之前)发出
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
mov-ax,
;cli取消对非常旧的8088兼容性的限制
;按此顺序成对使用这些说明
;在mov ss…之后,中断被禁用1次。。。
mov-ss,ax
mov sp,
;sti Decomment可实现非常古老的8088兼容性

为了处理中断,CPU需要一个正确设置的堆栈。
仅为了通过向ISR(中断服务路由)传递控制来服务中断,CPU按下
标志
CS
IP

然后,ISR可能,而且通常需要更多的堆栈

堆栈背后的基本假设是
SS:SP
下面的所有内容都被认为是空闲的、可用的内存。
当您将
SP
设置为7cfeh时,您只是说7cfeh以下的每个内存位置都是空闲的,其他人可以将其用作堆栈内存。
这就是你看到的垃圾。
请注意,列为200、220和240的地址位于堆栈指针的下方,在我看来,对这些地址使用“在顶部”虽然在比喻上是正确的,但有点混乱

如果您想确保自己是唯一一个干扰堆栈的人,请尽早(绝对在设置堆栈之前)发出
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
mov-ax,
;cli取消对非常旧的8088兼容性的限制
;按此顺序成对使用这些说明
;在mov ss…之后,中断被禁用1次。。。
mov-ss,ax
mov sp,
;sti Decomment可实现非常古老的8088兼容性

您可以演示如何生成二进制文件吗?@MargaretBloom我添加了更多信息在最开始时使用
cli
清除中断标志,而不将其设置回原位如何?我的意思是:SP以下以及堆栈末尾的所有内容都被认为是可以被需要覆盖的。而ISR需要。与你的问题无关。您可以使用将值
0x7cfe
直接移动到SP
mov sp,0x7cfe
。设置SS时需要使用寄存器。在设置SP时显式设置SS段是一个非常好的主意。它们作为一对SS:*SP*。某些环境(真实硬件)可能没有将SS设置为0。你似乎很依赖这个。如果希望堆栈从0x0000:0x7cfe(物理地址0x07cfe)向下扩展,则将其设置为该方式。这将执行异或ax,ax
mov-ss,ax
mov-sp,0x7cfe
。为了不限制你的代码,你可以把它放在下面0x07c00@MichaelPetch我刚刚开始学习这些东西,我需要一些时间来完全理解你的评论。不需要设置基本指针
bp
?感谢您展示了如何生成二进制文件?@MargaretBloom我添加了更多信息如何在最开始时用
cli
清除中断标志,而不将其设置回原位?我的意思是:SP以下以及堆栈末尾的所有内容都被认为是可以被需要覆盖的。而ISR需要。与你的问题无关。您可以使用将值
0x7cfe
直接移动到SP
mov sp,0x7cfe
。设置SS时需要使用寄存器。在设置SP时显式设置SS段是一个非常好的主意。它们作为一对SS:*SP*。某些环境(真实硬件)可能没有将SS设置为0。你似乎很依赖这个。如果希望堆栈从0x0000:0x7cfe(物理地址0x07cfe)向下扩展,则将其设置为该方式。这将执行xor ax,ax