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

Laz*_*zer 9 c++ stack

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

以下是调用函数时发生的步骤序列:

  1. 函数调用之外的指令地址被压入堆栈.这是CPU在函数返回后记住去向的方式.
  2. 房间是在堆栈上为功能的返回类型.这只是一个占位符.
  3. CPU跳转到函数的代码.
  4. 堆栈的当前顶部保存在称为堆栈帧的特殊指针中.
  5. 在此点之后添加到堆栈的所有内容都被视为函数的"本地".
  6. 所有函数参数都放在堆栈中.
  7. 函数内部的指令开始执行.
  8. 局部变量在定义时被压入堆栈.

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

例如,有三个参数a,b并且c从顶部放置在堆栈上

| a |
| b |
| c |
|   |
 ...
|___|
Run Code Online (Sandbox Code Playgroud)

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

ami*_*mit 15

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

由于自动变量的大小在编译时是已知的 - 编译器offset为每个变量标记,因此偏移量是从堆栈上的自动变量部分开始[或堆栈头部的位置确定的,两者都是有效的,具体实现可能取决于体系结构] ,它只通过以下方式访问它们:start + offset对于每个变量的偏移量.

  • @CaisManai 偏移量在编译时已知,不需要存储在内存中。 (2认同)

Luc*_*ore 1

不,他们不是。堆栈指针(通常是esp注册表)指向aesp+8h指向besp+16h指向c等等。没有必要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  
Run Code Online (Sandbox Code Playgroud)

所以你看,那里没有堆栈。运行时可以直接访问元素:dword ptr [x]等。