2015-06-30 34 views
3

我在装配中的知识有限,但我至少可以通读它并与相应的C或C++代码匹配。我可以看到函数参数是通过将它们推入堆栈或通过寄存器传递的,函数体使用一些寄存器来执行操作。但它似乎也使用了调用者使用的相同寄存器。这是否意味着调用者不能保证函数调用后寄存器的状态是相同的?如果在编译期间函数的整个主体是未知的,该怎么办?编译器如何处理这个问题?函数调用后寄存器的状态是什么?

+5

它取决于函数的[调用约定](https://en.wikipedia.org/wiki/Calling_convention)。对于x86 cdecl,EAX是返回值,ECX和EDX必须由调用者保存;其余的必须由被调用者保存。 –

+1

不仅是调用约定,还有特定编译器关于优化的策略以及它自己的特性。 – Robinson

+0

答案主要取决于编译器和操作系统。 –

回答

3

编译器生成的汇编代码遵循calling convention。调用约定通常指定

  • 如何传递给函数的参数
  • 返回值是如何从被调用函数传递给调用者
  • 哪些寄存器要保存一个函数调用内可以进行修改

如果被调用的所有函数遵循相同的调用约定,则不会发生使用相同寄存器的问题。

2

正如评论所暗示的那样,事实是没有这方面的标准。它完全留给你正在使用的特定C++编译器的实现者。

一个更明确的问题,如下所示:“使用ABI E编译带有编译器选项B的编译器A的版本N,为目标CPU D调用C的函数签名时,有什么保证,可见寄存器保存?“

在这种情况下,该特定工具集的专家(或手册)可以回答。你可以推断,对于任何类型的工业强度项目,这是一个错误的问题,因为随着编译器的发展,答案将会改变,而且你不希望这个事实影响你的可靠性程序。

这是一个很好的问题,因为很高兴知道编译器正在做什么 - 它有助于学习。但总的来说,黄金法则是在程序中向编译器表达清晰的简单逻辑,并允许编译器处理将该逻辑转换为优化机器代码的细节,在此代码中现代编译器非常出色。

+0

它不仅仅是编译器,而是大多数语言,体系结构/ CPU和操作系统。对于某些体系结构,有多个ABI(例如,ARM,x86 - 在Windows或Linux(OS-X?)上)。 – Olaf

+0

@Olaf的确如此,我的意思是“编译器”这个术语能够捕捉到所有这些,但我会在答案中明确指出。 –

+0

好吧,你是让它太泛泛......如果我在Windows上的x86架构上用C调用约定来声明函数foo(),那么......我会一直知道会发生什么,无论如何编译器版本(或其选项)。如果不是这样,你甚至不能调用OS库函数。 –

相关问题