C++ 在标准c++;程序执行

C++ 在标准c++;程序执行,c++,stack,execution,function-calls,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); } 现在发生的是当main开始执行时: 1.它将s推到堆栈上 2.它调用func() 3.func()将b、c、d、e、f、g推送到堆栈上 4.现在,当执行涉及a、b、c、d、e、f.g的代码时,为了知道a的值,必须弹出func(

我有以下代码:

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);
}
现在发生的是当main开始执行时:
1.它将s推到堆栈上
2.它调用func()
3.func()将b、c、d、e、f、g推送到堆栈上

4.现在,当执行涉及a、b、c、d、e、f.g的代码时,为了知道a的值,必须弹出func()的所有局部变量。然后检索a的值。现在,如果再次使用b.c.d.e.f.g,将如何检索它们的值(因为它们已经被弹出)?

本地变量以及参数实际上不会被推到堆栈上。相反,编译器会添加代码,将堆栈指针更改足够多以适应所有变量,然后在引用局部变量时,编译器会使用代码从堆栈指针的偏移量中获取值


我建议您查看示例程序的汇编程序输出,以了解它是如何工作的。

本地变量以及参数实际上并没有被推送到堆栈上。相反,编译器会添加代码,将堆栈指针更改足够多以适应所有变量,然后在引用局部变量时,编译器会使用代码从堆栈指针的偏移量中获取值


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

void func(int a)的等效代码

现在让我们看看下面代码的等效汇编代码:

    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 
} 
因此,尽管它们被推入堆栈(ESP或SP),但指向每个局部变量的指针也被存储,以便在需要时可以轻松访问它们

类似地,当代码需要使用变量a时,dword ptr[a]被简单地移动到寄存器EAX


注:技术上不推动,但调整以适应所有变量。(提供:Joachim Pileborg)

void func(int a)的等效代码

现在让我们看看下面代码的等效汇编代码:

    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 
} 
因此,尽管它们被推入堆栈(ESP或SP),但指向每个局部变量的指针也被存储,以便在需要时可以轻松访问它们

类似地,当代码需要使用变量a时,dword ptr[a]被简单地移动到寄存器EAX

注:技术上不推动,但调整以适应所有变量。(提供:约阿希姆·皮勒堡)

为了知道a的值,必须弹出func()的所有局部变量 这句话虽然在语法上模棱两可。我想你的意思是说变量在函数使用时弹出

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

为了知道a的值,必须弹出func()的所有局部变量 这句话虽然在语法上模棱两可。我想你的意思是说变量在函数使用时弹出

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