background image

浅析 和 C++中的调用约定

当您开始使用动态链接库,编写涉及其他语言中的函数代码时,你会遇到诸如
stdcall,safecall,cdecl 和 winapi 之类的词。这些调用约定定义了如何在运行时调用
外部函数,即使是单独编译,甚至可能是和不同的编译器和连接器。

  本文是一篇关于调用约定的小教程,旨在解释调用约定如何运作,并且与C 和 C + +
中书写动态链接库以及在 C#利用他们相关联。这可能对理解骨架代码有用。

  备注:这无关链接,而是使用动态数据库并在运行时间调用它们。

  一个调用约定定义了参数如何被传到堆栈,调用者或函数是否需要在结束调用后清理堆
栈。

  关于堆栈

  堆栈追踪函数的调用来源。而这通常是硬件通过使用注册簿来完成的,注册簿是对记忆
的指向标。按照惯例,一个堆栈开始是指向内存。随着每个项目都堆到堆栈上,堆栈指针
就会减少。当你从堆栈上删除数据时。

  一般来说,编译器具备一些设置可以指定堆栈可得的内存数量。堆栈可以保存以下三种
类型的数据:

 

返回地址;

 

函数参数;

本地变量。

  CPU 会有一些针对堆栈记忆分配的特殊指令。编译器会计算出所有本地变量和参数所需
要的内存量,并且相应地对其进行内存分配。在调用快结束时,准确的反面指令被调用来
减少同样的量。基本上,这些指令通过登记的数额减少了堆栈指针,并且在最后又相应地
增加了空间。

  返回地址

  当一个函数被调用的时候,CPU 要做的第一件事是在调用的函数生成时,计算出下一
个指令是什么。下表就是对该过程进行的一个小小的演示:

  Address 101

  Address 102 Call Function 201

  Address 103...

  ...