装配 - 如何修改堆栈大小?

时间:2015-12-31 09:56:42

标签: windows assembly x86

我是汇编编程的新手,我使用的是使用内存堆栈的push和pop指令。 那么,什么是堆栈默认大小,如何修改它以及它的大小是什么限制?

2 个答案:

答案 0 :(得分:3)

无论加载("加载程序")你的程序到内存中,并将控制传递给它,确定堆栈所在的内存位置,以及可用的空间大小堆栈。

这是通过加载堆栈指针的简单技巧实现的,通常在调用/跳转到代码之前使用 MOV ESP,... 指令。然后,您的程序将使用提供的堆栈区域。

如果您的程序使用太多,它将写入超出分配的堆栈区域的末尾。这是一个程序错误,因为可能会在应用程序中为某些其他目的分配超过结尾的内存。写入其他内存可能会改变程序行为(例如," bug"),当使用该内存时,找到该错误的原因很可能很困难(人们认为堆栈不会出现问题) ; t损坏程序数据,反之亦然)。

如果你的应用程序想要使用更大的堆栈,通常你所要做的就是分配你自己的区域,大到足以满足你的需要,并做一个MOV ESP,......你自己将堆栈设置到所选的位置。如何分配区域取决于您运行的执行环境。 (您需要尊重ESP约定:必须是4的倍数,应该初始化到缓存行的底部,通常可以初始化到虚拟内存页面的底部)。

当"切换"通常是一个好主意。堆栈以保存加载程序提供的ESP的旧值,并在将控制权返回到加载程序/调用者/操作系统之前将ESP恢复为该旧值。同样,您应该释放不再使用的扩展堆栈空间。

如果您事先知道所需的堆栈空间量,此方案将起作用。在实践中,这很难猜测" (如果您的代码具有深深嵌套的递归算法,则可能无法实现)。因此,您可以选择比您需要的更大的数字(ick),或者当程序清楚需要更多时,您可以使用有组织的方法来切换堆栈。 有关详细信息,请参阅How does a stackless language work?

答案 1 :(得分:1)

堆栈大小取决于很多因素。 这取决于你启动堆栈的位置,你有多少内存,你正在使用什么CPU等。 您正在使用的CPU不称为" Windows CPU"。 如果要指定正在使用的CPU,则需要详细指定该CPU的名称,并且非常重要的是指定CPU的体系结构。在这种情况下,您可能正在使用x86架构。在这里a link了解CPU架构是什么。

这是x86架构的内存映射:


All addresses Before 0X100000 - Free
0x100000 - 0xc0000 - BIOS
0xc0000 - 0xa0000 - Video Memory
0xa0000 - 0x9fc00 - Extended BIOS data area
0x9fC00 - 0x7e00 - Free
0x7e00 - 0x7c00 - Boot loader
0x7c00 - 0x500 - Free
0x500 - 0x400 - BIOS data area
0x400 - 0x00 - Interupt vector table
在x86中,堆栈信息由两个寄存器保存:

    Base pointer (bp): Holds starting address of the stack
    Stack pointer (sp): Holds the address in which next value will be stored
这些寄存器在不同模式下有不同的名称:

                            Base pointer           Stack pointer
    16 bit real mode:       bp                     sp
    32 bit protected mode:  ebp                    esp
    64 bit mode:            rbp                    rsp
设置堆栈时,堆栈指针和基址指针获得相同的地址。

堆栈设置在基址指针寄存器中指定的地址中 您可以在内存中的任何位置设置堆栈,该堆栈是免费的,堆栈会向下扩展。

每次你"推"在堆栈上的某些东西,该值存储在堆栈指针指定的地址中(与开头的基址指针相同),并且堆栈指针寄存器递减。

每次你" pop"来自堆栈的东西,存储在堆栈指针寄存器指定的地址中的值存储在程序员指定的寄存器中,堆栈指针寄存器递增。
在16位实模式下,您可以推送"和" pop" 16位。所以每次你推动"或"弹出",堆栈指针寄存器递减或递增0x02,因为每个地址保持8位。

在32位保护模式下,您可以推送"和" pop" 32位。所以每次你推动"或" pop",堆栈指针寄存器递减或递增0x04,因为每个地址保持8位。

你必须在正确的位置设置堆栈,这取决于你将要使用多少个值"推动"。

如果你继续推动"你的堆栈不断向下增长,在某些时候你的堆栈可能会覆盖某些东西。因此,明智的做法是将堆栈设置在内存中的一个地址中,堆栈有足够的空间向下生长。

例如:
如果你将堆栈设置为0x7c00,就在引导加载程序的下方,你就可以推送"太多的值,您的堆栈可能会在某个时间点覆盖BIOS数据区域,从而导致很多错误。

到目前为止,您应该对堆栈及其大小有一个基本的了解。

相关问题