每一个应用程序(进程)都会有一个独立的4GB内存空间,但是并不能随便用,实际使用的时候要向操作系统申请,称之为内存的申请。
堆栈 就是一块内存,只不过不是程序员自己申请的,它是程序在启动执行的时候,操作系统为我们分配好了的这样一块内存。
堆栈这块内存 主要是给程序执行的时候用的,程序在执行的时候需要存储临时数据等等,这些信息都是存在堆栈里面的。
此处堆栈 与数据结构里面的 堆栈不是一个概念。
任何一个程序,它使用的关键数据,一定在堆栈中有体现。堆栈可以看成是程序的心脏,所有重要的数据都在这里面出现。无论是做病毒,反病毒,外挂,漏洞的,堆栈都是要了解的重中之重。对于普通正向工程师,堆栈可能不会关注,因为是操作系统为他分的,使用的时候也不需要管其中的细节。但是做安全的,底层的,堆栈这块一定要了解的比较清楚。
拖拽一个exe到DTDEBUG,查看FS对应的内存地址,去地址窗口查看,可查看操作系统为堆栈分配的堆栈空间,上图是1bc000~1c0000。
一般内存使用的时候,都是从小到大(1bc000开始使用,直到1c0000)。但是堆栈的内存使用,是从大到小(1c0000开始使用,直到1bc000)。
如果这块内存用完了,程序会出错,叫堆栈溢出。
如何查看程序当前使用到堆栈哪里了? 使用栈指针寄存器查看 ESP对应的地址
当我们写程序,使用了堆栈里面的内存以后,要告诉当前程序,我现在用到哪里了。–需要修改ESP的值。(假设使用了8个字节–2个dword,sub esp,8–内存使用由大地址到小地址,新使用了8个字节,esp要减8)
内存使用完,不想要了,要把栈顶再恢复到原来的位置。(还是假设使用了8个字节,add esp,8–修改栈顶指针至原来位置即可。原来的值没有影响,后面使用可直接覆盖即可。)
C语言为什么局部变量一定要赋初值? 原因就在此,如果不赋初值,可能把堆栈中之前的值随便给你了。
PUSH 将数据压入栈顶,并自动修改ESP的值,无需我们手动修改。
学习指令不要死记硬背,要灵活,我们前面使用mov add sub同样实现了push做的事情。
pop指令,将栈顶指针的值,放到相应的容器中,栈顶指针的值自动加2/4。