标准c ++程序执行期间的函数调用

时间:2012-09-27 06:16:51

标签: c++ stack execution function-calls

我有以下代码:

int func(int a)
{
  int b=2;
  int c,d,e,f,g;
  //some code which involves a,b,c,d,e,f,g
} 

int main()
{
 int s=3;
 func(s);
}

现在发生的事情是当主要开始执行时:
它将s推到堆栈上 2.它调用func()
3.func()将b,c,d,e,f,g推到堆栈上 4.当执行涉及a,b,c,d,e,f.g的代码时,为了知道func()的所有局部变量的值,必须弹出。然后检索一个值。现在如果再次使用b.c.d.e.f.g,它们的值将如何被检索(因为它们已被弹出)?

3 个答案:

答案 0 :(得分:6)

局部变量以及参数实际上并未在堆栈中推送。相反,编译器添加代码来更改堆栈指针足以适应所有变量,然后在引用局部变量时,编译器有代码从堆栈指针中获取 offset 的值。

我建议您查看示例程序的汇编器输出,以了解它的工作原理。

答案 1 :(得分:1)

void func(int a)

的等效代码
    void func(int a)
{
00413880  push        ebp  
00413881  mov         ebp,esp 
00413883  sub         esp,108h 
00413889  push        ebx  
0041388A  push        esi  
0041388B  push        edi  
0041388C  lea         edi,[ebp-108h] 
00413892  mov         ecx,42h 
00413897  mov         eax,0CCCCCCCCh 
0041389C  rep stos    dword ptr es:[edi] 
  int b=2;
0041389E  mov         dword ptr [b],2 
  int c,d,e,f,g;
  //some code which involves a,b,c,d,e,f,g
} 

现在让我们看一下以下代码::

的等效汇编代码
    void func(int a)
{
  int b=2;
  int c,d,e,f,g;
  c = 10 ;
  d = 15 ;
  e = 20 ;
  a = a + 2 ;
} 

汇编代码::

    void func(int a)
{
00413880  push        ebp  
00413881  mov         ebp,esp 
00413883  sub         esp,108h 
00413889  push        ebx  
0041388A  push        esi  
0041388B  push        edi  
0041388C  lea         edi,[ebp-108h] 
00413892  mov         ecx,42h 
00413897  mov         eax,0CCCCCCCCh 
0041389C  rep stos    dword ptr es:[edi] 
  int b=2;
0041389E  mov         dword ptr [b],2 
  int c,d,e,f,g;
  c = 10 ;
004138A5  mov         dword ptr [c],0Ah 
  d = 15 ;
004138AC  mov         dword ptr [d],0Fh 
  e = 20 ;
004138B3  mov         dword ptr [e],14h 
  a = a + 2 ;
004138BA  mov         eax,dword ptr [a] 
004138BD  add         eax,2 
004138C0  mov         dword ptr [a],eax 
} 

因此,尽管它们被推入Stack(ESP或SP),但是也存储了指向每个局部变量的指针,因此,可以在需要时轻松访问它们。

例如,当代码需要使用变量a 时, dword ptr [a] 只需移动到注册 EAX

注意:技术上没有按下但是经过调整以适应所有变量。 (礼貌:Joachim Pileborg)

答案 2 :(得分:0)

  

为了知道func()的所有局部变量的值必须弹出   这条线虽然在语法上含糊不清。我假设你的意思是说当变量被函数使用时会弹出变量。

但实际情况是局部变量仅在函数返回调用者时弹出。 只要它们是自动的。 另一方面,当函数想要访问(读/写)变量时。它使用距离基数的偏移量(距离)来访问它们,因此在访问评估时不会出现变量弹出的问题。