内存中栈的具体表现

本文通过一个简单的C语言程序,详细展示了栈在内存中的表现形式。从设置断点开始,逐步跟踪程序执行过程中的寄存器变化及内存栈的变化情况,帮助理解栈的工作原理。

栈在内存中到底是如何表现的呢?我们来做一个实例调试一下。

 

代码如下:

 

#include <stdio.h>

void main()
{
 _asm
 {
  push 0x12345678
  push 0x11112222 
  pop eax
  pop ebx
 }
}

 

按F9下一个断点,然后按F5进行调试。反汇编窗口如下

 

5:        _asm
6:        {
7:            push 0x12345678
00401028   push        12345678h
8:            push 0x11112222
0040102D   push        11112222h
9:            pop eax
00401032   pop         eax
10:           pop ebx
00401033   pop         ebx
11:       }

寄存器窗口如下:

 

EAX = CCCCCCCC EBX = 7FFDF000 ECX = 00000000 EDX = 00191030 ESI = 00000000

EDI = 0012FF48 EIP = 00401028 ESP = 0012FEFC EBP = 0012FF48 EFL = 00000202

 

EBP的地址是0012FF48,ESP的地址是0012FEFC,通过这两个值就可以找到栈

 

0012FEE4  00 00 00 00 02 00 00 00 30 2F  ........0/

0012FEEE  42 00 83 00 00 00 E0 06 19 00  B.........
0012FEF8  1C FF 12 00 00 00 00 00 00 00  ..........
0012FF02  00 00 00 F0 FD 7F CC CC CC CC  ...瘕.烫烫
0012FF0C  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF16  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF20  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF2A  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF34  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF3E  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫

0012FF48  88 FF 12 00 89 11 40 00 01 00  ......@...
0012FF52  00 00 B8 0F 19 00 30 10 19 00  ......0...

 

然后按F11单步执行,这时发现

 

EAX = CCCCCCCC EBX = 7FFDF000 ECX = 00000000 EDX = 00191030 ESI = 00000000 EDI = 0012FF48 EIP = 0040102D ESP = 0012FEF8 EBP = 0012FF48 EFL = 00000202

 

0012FEE4  00 00 00 00 02 00 00 00 30 2F  ........0/
0012FEEE  42 00 83 00 00 00 E0 06 19 00  B.........
0012FEF8  78 56 34 12 00 00 00 00 00 00  xV4.......
0012FF02  00 00 00 F0 FD 7F CC CC CC CC  ...瘕.烫烫
0012FF0C  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF16  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF20  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF2A  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF34  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF3E  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF48  88 FF 12 00 89 11 40 00 01 00  ......@...
0012FF52  00 00 B8 0F 19 00 30 10 19 00  ......0...
0012FF5C  00 00 00 00 00 00 00 00 00 F0  ..........

 


 

然后再单步

 

 EAX = CCCCCCCC EBX = 7FFDF000 ECX = 00000000 EDX = 00191030 ESI = 00000000 EDI = 0012FF48 EIP = 00401032 ESP = 0012FEF4 EBP = 0012FF48 EFL = 00000202

 

0012FEE4  00 00 00 00 02 00 00 00 30 2F  ........0/
0012FEEE  42 00 83 00 00 00 22 22 11 11  B.....""..
0012FEF8  78 56 34 12 00 00 00 00 00 00  xV4.......
0012FF02  00 00 00 F0 FD 7F CC CC CC CC  ...瘕.烫烫
0012FF0C  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF16  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF20  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF2A  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF34  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF3E  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF48  88 FF 12 00 89 11 40 00 01 00  ......@...
0012FF52  00 00 B8 0F 19 00 30 10 19 00  ......0...

 

 

然后再单步

 

 EAX = 11112222 EBX = 7FFDF000 ECX = 00000000 EDX = 00191030 ESI = 00000000 EDI = 0012FF48 EIP = 00401033 ESP = 0012FEF8 EBP = 0012FF48 EFL = 00000202

 

0012FEE4  00 00 00 00 02 00 00 00 30 2F  ........0/
0012FEEE  42 00 83 00 00 00 22 22 11 11  B.....""..
0012FEF8  78 56 34 12 00 00 00 00 00 00  xV4.......
0012FF02  00 00 00 F0 FD 7F CC CC CC CC  ...瘕.烫烫
0012FF0C  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF16  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF20  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF2A  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF34  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF3E  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF48  88 FF 12 00 89 11 40 00 01 00  ......@...
0012FF52  00 00 B8 0F 19 00 30 10 19 00  ......0...

 

然后再单步

 EAX = 11112222 EBX = 12345678 ECX = 00000000 EDX = 00191030 ESI = 00000000 EDI = 0012FF48 EIP = 00401034 ESP = 0012FEFC EBP = 0012FF48 EFL = 00000202

 

0012FEE4  00 00 00 00 02 00 00 00 30 2F  ........0/
0012FEEE  42 00 83 00 00 00 22 22 11 11  B.....""..
0012FEF8  78 56 34 12 00 00 00 00 00 00  xV4.......
0012FF02  00 00 00 F0 FD 7F CC CC CC CC  ...瘕.烫烫
0012FF0C  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF16  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF20  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF2A  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF34  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF3E  CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫
0012FF48  88 FF 12 00 89 11 40 00 01 00  ......@...
0012FF52  00 00 B8 0F 19 00 30 10 19 00  ......0...

 
<think>嗯,用户想了解内存中的存储结构和表现形式。首先,我需要回忆一下关于内存管理的知识,特别是区的特点。根据之前提供的引用资料,比如引用[2]和引用[4],面提到是由系统管理的,存放函数内的变量、参数等,采用后进先出的结构。 用户可能对的具体存储方式不太清楚,比如地址增长方向,帧的结构,或者如何管理局部变量和函数调用。我需要先解释的基本概念,然后详细说明它的存储结构,比如从高地址向低地址扩展,这一点在引用[4]中提到过。还要提到指针和基址指针的作用,这样用户能理解是如何动态调整的。 另外,中的内容,如函数参数、返回地址、局部变量,这些都需要分点说明,让结构更清晰。可能用户还想知道与其他内存区域(比如堆)的区别,所以需要对比一下,比如的大小限制和自动管理的特点。 还要注意用户可能的实际应用场景,比如编程时局部变量的存储,或者递归调用时的溢出问题。可以举例子,比如函数调用时的变化,或者使用C语言的代码片段来说明局部变量如何在上分配。 需要确保使用正确的中文术语,避免技术术语错误,同时引用相关的资料来支持解释,比如引用[3]提到变量名存储在区,而复杂结构在堆区。这可能帮助用户理解和堆的不同用途。 最后,生成的相关问题要围绕的扩展方向、存储内容、与堆的区别以及溢出等常见问题,这样用户如果有进一步疑问,可以自行探索这些方向。整个回答需要结构清晰,逐步展开,确保用户能够逐步理解的存储结构和表现形式。</think>### 内存中的存储结构与表现形式 #### 1. **的基本特性** 内存中用于管理**函数调用、局部变量、函数参数**的动态存储区域[^2][^4],其核心特征包括: - **后进先出(LIFO)**:最后分配的内存最先释放。 - **自动管理**:由编译器自动分配和回收,无需手动干预。 - **高地址向低地址扩展**:内存的分配方向与堆相反(堆由低地址向高地址扩展)[^4]。 #### 2. **的存储结构** 的存储结构通过**帧(Stack Frame)**实现,每个函数调用对应一个帧,包含以下核心内容: $$ \begin{aligned} &\text{顶(低地址)} \\ &\quad \downarrow \text{局部变量} \\ &\quad \downarrow \text{函数返回地址} \\ &\quad \downarrow \text{前一个帧的基址(EBP)} \\ &\quad \downarrow \text{函数参数} \\ &\text{底(高地址)} \end{aligned} $$ 具体说明: 1. **函数参数**:按从右到左的顺序压入(如C语言)。 2. **返回地址**:保存函数执行完毕后应返回的指令地址。 3. **前帧基址(EBP)**:用于恢复调用者的帧。 4. **局部变量**:在函数内部声明的变量,按声明顺序入[^3][^4]。 #### 3. **的操作示例** 以C语言函数调用为例: ```c void func(int a, int b) { int c = 10; // ... } int main() { func(5, 8); return 0; } ``` 内存的变化: 1. `main`调用`func`时,参数`8`和`5`依次压。 2. 将返回地址(`main`中下一条指令地址)压。 3. 保存`main`的EBP,并设置新的EBP指向当前顶。 4. 为局部变量`c`分配空间,存入值`10`。 #### 4. **的局限性** - **固定大小**:空间有限(如Linux默认约8MB),过度使用会导致**溢出**(如无限递归)。 - **数据生命周期**:局部变量随函数结束自动销毁[^3]。 #### 5. **与堆的对比** | 特性 | | 堆 | |--------------|-----------------------------|-----------------------------| | 管理方式 | 编译器自动分配/释放 | 手动申请/释放(如`malloc`) | | 扩展方向 | 高地址 → 低地址 | 低地址 → 高地址 | | 访问速度 | 快 | 慢 | | 数据类型 | 局部变量、函数参数 | 动态分配的数据结构 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值