大会 – 如何修改堆栈大小?

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

无论将程序加载(“加载程序”)到内存中,并将控制权交给内存,它将确定堆栈所在的内存位置以及堆栈有多少可用空间。

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

如果你的程序使用太多,它将超出分配的堆栈区域的末尾写入。 这是一个程序错误,因为最后的内存可能被分配给应用程序中的其他用途。 写在其他内存上可能会改变程序行为(例如,“错误”),并找到该错误的原因可能是困难的(人们认为堆栈不会损坏程序数据和恶意反之亦然)。

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

当“切换”堆栈以保存由加载器提供的ESP的旧值时通常是一个好主意,并且在将控制权返回给加载器/调用者/ OS之前将ESP恢复为旧值。 同样,你应该释放不再使用的扩展堆栈空间。

如果您事先知道您需要的堆栈空间量,该方案将起作用。 在实践中,这很难“猜测”(如果你的代码有嵌套的递归算法,这可能是不可能的)。 所以你可以选择一个比你需要的数量更大的数字(ick),或者当程序清楚它需要更多的时候,你可以使用有组织的方法来切换堆栈。 请参阅无堆栈语言如何工作? 进行更多的讨论。

堆栈大小取决于很多因素。 这取决于你在哪里启动堆栈,你有多少内存,你正在使用哪个CPU等。你使用的CPU不叫“Windows CPU”。 如果您正在指定正在使用的CPU,请详细指定该CPU的名称,而且非常重要的是指定CPU的体系结构。 在这种情况下,您可能正在使用x86架构。 这是一个链接 ,了解什么是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 

当你建立一个堆栈时,堆栈指针和基址指针会得到相同的地址。

堆栈设置在基址指针寄存器中指定的地址中。
你可以在内存中任意位置设置你的堆栈,并且堆栈向下增长。

每次你将某些东西“推”到堆栈中时,该值将被存储在由堆栈指针指定的地址中(与起始处的基址指针相同),堆栈指针寄存器递减。

每次从堆栈中“弹出”某个东西时,存储在由堆栈指针寄存器指定的地址中的值将被存储在由编程器指定的寄存器中,堆栈指针寄存器将递增。

在16位真实模式下,您可以“推”和“弹出”16位。 所以每次你“push”或“pop”时,堆栈指针寄存器减1或增加0x02,因为每个地址都有8位。

在32位保护模式下,您可以“推”和“弹出”32位。 所以每次你“push”或者“pop”时,堆栈指针寄存器会递减或递增0x04,因为每个地址都有8位。

你将不得不在正确的地方设置堆栈,取决于你要“推”多少个值。

如果你一直“推”你的堆栈不断增长,在某些时候你的堆栈可能会覆盖一些东西。 因此,明智的做法是在内存中有足够的空间让堆栈向下生长。

例如:
如果您将堆栈设置为0x7c00,就在引导加载程序的下方,并且“推”太多的值,那么堆栈可能会在某个时间点覆盖BIOS数据区域,这会导致很多错误。

你现在应该有一个堆栈的基本概念和大小。