如何从堆栈访问函数局部变量?

时间:2012-02-12 09:11:12

标签: c++ stack

来自http://www.learncpp.com/cpp-tutorial/79-the-stack-and-the-heap/

  

以下是函数所在的步骤序列   称为:

     
      
  1. 函数调用之外的指令地址被压入堆栈。这就是CPU如何记住之后的去处   函数返回。
  2.   
  3. 在堆栈上为函数的返回类型创建了空间。这只是一个占位符。
  4.   
  5. CPU跳转到函数的代码。
  6.   
  7. 堆栈的当前顶部保存在一个称为堆栈帧的特殊指针中。
  8.   
  9. 此点之后添加到堆栈中的所有内容都被视为函数的“本地”。
  10.   
  11. 所有函数参数都放在堆栈上。
  12.   
  13. 函数内部的指令开始执行。
  14.   
  15. 局部变量在定义时被压入堆栈。
  16.   

我不确定#6点是如何工作的。如果所有函数参数都放在堆栈上,它们是如何被访问的?

例如,如果有三个参数abc并且从顶部放置在堆栈上

| a |
| b |
| c |
|   |
 ...
|___|

现在当函数想要访问c时会发生什么? ab被弹出了吗?

3 个答案:

答案 0 :(得分:14)

堆栈是隐喻堆栈。记住它仍然是一个内存,所以如果你知道你在寻找什么,你可以访问每个地址而不会弹出其余的地址。

由于自动变量的大小在编译时已知 - 编译器为每个变量标记offset,因此偏移量是从堆栈上的自动变量部分开始[或堆栈的位置]确定的head,两者都是有效的,具体实现取决于架构],并且它仅通过start + offset访问它们,用于每个变量的偏移量。

答案 1 :(得分:1)

不,他们不是。堆栈指针(通常是esp注册表)指向aesp+8h指向besp+16h指向c,依此类推。 <{1}}不需要弹出。

请注意,这是一个实现细节。你不应该担心这些。我给出的数字纯粹是理论上的,在某些体系结构中,降序地址被赋予后面的参数,而另一些则相反。不能保证会发生这种情况。

编辑:在我看来,这不是一个非常可靠的信息来源。它讲的是堆栈和堆,但这些都是实现细节,甚至可能不存在。

对于通过堆栈实现的任何内容,标准中没有任何限制。例如,我生成了以下代码:

a

所以你看,那里没有堆叠。运行时可以直接访问元素:void foo(int x, int y, int z) { 01241380 push ebp 01241381 mov ebp,esp 01241383 sub esp,0CCh 01241389 push ebx 0124138A push esi 0124138B push edi 0124138C lea edi,[ebp-0CCh] 01241392 mov ecx,33h 01241397 mov eax,0CCCCCCCCh 0124139C rep stos dword ptr es:[edi] int c = x; 0124139E mov eax,dword ptr [x] 012413A1 mov dword ptr [c],eax c = y; 012413A4 mov eax,dword ptr [y] 012413A7 mov dword ptr [c],eax c = z; 012413AA mov eax,dword ptr [z] 012413AD mov dword ptr [c],eax } 012413B0 pop edi 012413B1 pop esi 012413B2 pop ebx 012413B3 mov esp,ebp 012413B5 pop ebp 等。

答案 2 :(得分:0)

它使用堆栈指针和相对地址来指出c。