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

function calls during a standard c++ program execution

本文关键字:函数调用 执行期 C++ 程序 标准      更新时间:2023-10-16

我有以下代码:

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.It 将 s 推送到堆栈
上2.It 调用 func()
3.func() 将 B,C,D,E,F,G 推送到堆栈
上4.现在,当涉及 a,b,c,d,e,f.g 的代码被执行时,为了知道 func() 的所有局部变量的值,必须弹出。然后检索 a 的值。现在,如果要再次使用 b.c.d.e.f.g,将如何检索它们的值(因为它们已经被弹出)?

局部变量和参数实际上并没有推送到堆栈上。相反,编译器添加代码以将堆栈指针更改为足以适合所有变量的程度,然后在引用局部变量时,编译器具有从堆栈指针的偏移量中获取值的代码。

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

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提供)

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

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