函数调用约定和堆栈
1 什么是堆栈
编译器一般使用堆栈实现函数调用。堆栈是存储器的一个区域,嵌入式环境有时需要程序员自己定义一个数组作为堆栈。Windows为每个线程自动维护一个堆栈,堆栈的大小可以设置。编译器使用堆栈来堆放每个函数的参数、局部变量等信息。
函数调用经常是嵌套的,在同一时刻,堆栈中会有多个函数的信息,每个函数占用一个连续的区域。一个函数占用的区域被称作帧(frame)。
编译器从高地址开始使用堆栈。
假设我们定义一个数组a[1024]作为堆栈空间,一开始栈顶指针指向a[1023]。如果栈里有两个函数a和b,且a调用了b,栈顶指针会指向函数b的帧。如果函数b返回。栈顶指针就指向函数a的帧。如果在栈里放了太多东西造成溢出,破坏的是a[0]上面的东西。
在多线程(任务)环境,CPU的堆栈指针指向的存储器区域就是当前使用的堆栈。切换线程的一个重要工作,就是将堆栈指针设为当前线程的堆栈栈顶地址。
不同CPU,不同编译器的堆栈布局、函数调用方法都可能不同,但堆栈的基本概念是一样的。
2 函数调用约定
函数调用约定包括传递参数的顺序,谁负责清理参数占用的堆栈等,例如 :
|
参数传递顺序 |
谁负责清理参数占用的堆栈 |
__pascal |
从左到右 |
调用者 |
__stdcall |
从右到左 |
被调函数 |
__cdecl |
从右到左 |
调用者 |
调用函数的代码和被调函数必须采用相同的函数的调用约定,程序才能正常运行。在Windows上,__cdecl是C/C++程序的缺省函数调用约定。
在有的cpu上,编译器会用寄存器传递参数,函数使用的堆栈由被调函数分配和释放。这种调用约定在行为上和__cdecl有一个共同点:实参和形参数目不符不会导致堆栈错误。
不过,即使用寄存器传递参数,编译器在进入函数时,还是会将寄存器里的参数存入堆栈指定位置。参数和局部变量一样应该在堆栈中有一席之地。参数可以被理解为由调用函数指定初值的局部变量。
分享到:
相关推荐
C++函数调用约定是编程过程中非常重要的概念,它规定了函数调用时参数传递的顺序、谁负责清理堆栈以及函数名是否需要修饰。在Visual C/C++编译器中,有四种主要的函数调用约定:__cdecl、__stdcall、__fastcall和...
要实现高效获取函数调用堆栈,需要了解函数调用堆栈和异常处理的背景知识。 1.1 函数调用堆栈 函数调用堆栈是一种重要的数据结构,在程序执行过程中,它记录了函数的调用关系和参数信息。C++中有多种调用约定,如_...
函数调用约定(Calling Convention)定义了函数调用者与被调用函数之间的交互规则,包括参数如何传递、返回值如何传递、调用前后堆栈的状态如何管理等内容。这种约定是必要的,因为不同的编程环境可能会有不同的实现...
函数调用约定是编程语言中规定函数调用过程的一个重要机制,主要涉及到参数传递和堆栈清理的责任分配。在C和C++中,不同的调用约定适用于不同的场景,特别是涉及到DLL(动态链接库)和Win API函数时,选择正确的调用...
在x86架构下,函数调用约定转换的关键在于理解参数传递和堆栈清理的规则。例如,尽管函数声明中使用了不同的调用约定,如`__cdecl`和`__stdcall`,但只要我们知道参数是如何压栈和返回值是如何处理的,就可以通过...
### C/C++语言函数参数传递及函数调用约定的探讨 #### 摘要 本文主要探讨了C/C++语言中函数之间的参数...通过合理选择参数传递方式(值传递或地址传递)和合适的函数调用约定,可以显著提高程序的性能和可维护性。
本文将深入探讨与`chkesp`相关的函数调用方式,特别是其在堆栈管理和函数调用约定中的应用。 #### 二、堆栈的基本概念 1. **什么是堆栈?** - 堆栈是一种特殊的内存区域,用于存储函数调用过程中的参数、局部变量...
### 函数调用约定与函数名称修饰规则 #### 调用约定(Calling Convention) 调用约定是指在程序设计语言中为了实现函数调用而建立的一种协议。这种协议规定了该语言的函数中的参数传送方式、参数是否可变以及由谁...
本篇文章将深入探讨如何从汇编代码中理解C语言程序的执行流程,并通过具体的例子来解释调用约定(Calling Conventions)和堆栈的工作原理。 #### 二、调用约定简介 调用约定(Calling Convention)规定了函数调用时...
在C和C++编程中,函数的调用约定(Calling ...总之,理解并正确使用函数调用约定和函数名修饰规则是避免C和C++程序中常见错误的关键。正确应用这些规则可以保证程序的正确链接和执行,提高代码的兼容性和可维护性。
调用约定对于函数调用的效率和兼容性至关重要。理解不同调用约定的特点和适用场景有助于开发更高效、更易维护的代码。在开发DLL时尤其需要注意选择正确的调用约定,以确保与其他语言编写的模块之间的互操作性。此外...
函数调用约定不仅关系到函数参数的传递方式,还涉及到函数调用后的堆栈维护,这些都是程序设计中的基础和核心问题。了解C语言的各种函数调用约定,对于深入学习和高效编程有着重要意义。 首先,让我们从最为基本的...
在计算机科学中,函数调用堆栈(也称为调用栈或执行栈)是程序运行时内存中的一个重要组成部分,主要用于管理函数...掌握函数调用堆栈的概念对于理解和调试程序,特别是在低级编程和系统级开发中,具有至关重要的作用。
该文档主要介绍了在C语言中,函数调用时的参数传递和堆栈管理问题,以及不同的函数调用约定。在高级语言编译成机器码时,计算机无法自动识别参数信息,因此需要依赖特定的参数传递机制和规则来确保函数能正确接收其...
在本文中,我们将深入探讨两种常见的函数调用约定:stdcall和cdecl。 首先,stdcall调用约定,也称为PASCAL调用约定,尤其在Microsoft C++编译器中常见。它规定参数从右到左压入堆栈,即最右边的参数最先被压入,...
7. **调用约定**:不同函数调用约定(如cdecl、stdcall、fastcall等)会影响参数传递顺序和清理责任。比如,cdecl约定中,参数从右向左压栈,调用者负责清理参数;stdcall约定中,参数也是从右向左压栈,但被调用者...
综上所述,选择哪种函数调用约定取决于具体的应用场景和需求。`__stdcall`适用于需要减少调用者负担的场景,而`__cdecl`则更适用于需要优化函数性能和通用性的场合。对于开发者而言,理解这些基本概念对于编写高效、...
在`main`函数中,调用`fun`函数时,首先会将参数`0x8899`和`0x1100`按照`__cdecl`调用约定,从右到左依次压入栈中。这符合Intel架构下的函数调用规则。 **2. 调用函数** 接下来执行`call @ILT+0(_fun)`指令,该指令...
2. **函数调用约定**:不同的系统和编译器有不同的函数调用约定,比如stdcall、cdecl等。在易语言中,需要明确调用约定,以正确地将参数压入堆栈并清理堆栈。 3. **参数传递**:在动态堆栈调用中,函数参数通常通过...
__cdecl 是 C 和 C++ 默认的函数调用约定。在 __cdecl 约定下,函数的参数是从右向左压栈的,也就是说,最后的参数最先入栈,而最先的参数最后入栈。函数的调用方负责清理栈中的参数,即在函数返回之后,调用方需要...