我已经明白,应该将堆栈指针与2字节边界对齐。换句话说,不应该将SP设置为以0xF(或任何其他奇数)结尾的值。
如果我使用0xFFFF作为SP,会发生什么?所有64kB都可用,还是少一个字节?
如果我想要一个1024字节的堆栈大小,我应该将SP设置为0x3FF还是0x400?例如是SS(堆栈段)指向要使用的字节?
他们声明here一个人也不应该使用以0xE结尾的SP地址,“浪费字节在0x..E和0x..F ”。怎么样?
答案 0 :(得分:1)
x86堆栈完全降序 完整表示堆栈指针指向最后推送的项目。这与空降序/升序堆栈形成对比,其中堆栈指针指向下一个空闲位置。
基本上,这归结为push ax
sub sp, 02h
mov WORD [sp], ax
当您将堆栈指针sp
设置为地址 X 时, X 被视为最后一个项目的位置,因此不会被使用。
如果将sp
设置为0xe,则推送将sp
移动到0xe - 2 = 0xc并在其中写入其操作数。不触及0xe及以上的存储器。
使用sp
的奇数地址会对性能产生负面影响,因为未对齐的内存访问的延迟可能是对齐访问的延迟的两倍。
对于小于DRAM总线宽度的数量(在写入时为8字节),这种惩罚会有所降低
考虑堆栈的使用频率,值得保持对齐。
从sp
的奇数地址开始将导致堆栈指针达到1时出现问题。
推送会将sp
设置为0xffff,但随后写入一个字将触发#SS,因为较高的字节超出ss
限制。
反过来,使用混乱的堆栈引发异常将引发另一个CPU将作为#DF发送的#SS。
但堆栈仍然混乱,因此产生第三个异常,三重故障,CPU将重置
因此,堆栈指针不对齐没有任何好处。
如果你想要大小 S 的堆栈,你将sp
设置为 S mod 2 16 授予2< = S < = 64KiB
您可以通过写下 S 的小值(例如4)来检查这是否正确。
您还可以检查设置sp
为0将为您提供64KiB堆栈,这是实际模式中自然可用的最大尺寸。