函数调用后寄存器的状态是什么?

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

5
这取决于函数的调用约定。对于x86 cdecl,EAX是返回值,ECX和EDX必须由调用方保存,其余部分则必须由被调用方保存。 - Colonel Thirty Two
1
不仅仅是调用约定,还包括特定编译器的优化策略以及其自身的特点。 - Robinson
答案主要取决于编译器和操作系统。 - Jabberwocky
对于ARM架构,它是ARM过程调用标准(AAPCS)和特定于语言的应用程序二进制接口(ABI)。您可以从其网站免费下载它们。 - too honest for this site
这个问题目前太过宽泛。您需要更详细地说明。此外,实际上这是多个问题。 - too honest for this site
请参考这个问题了解更多细节。 - molbdnilo
2个回答

2
正如评论中所提到的,事实上并没有标准规定这一点。这完全取决于您使用的特定C++编译器的实现者。
如果您提出更明确的问题,例如:“在使用编译器A的版本N和编译器选项B进行编译时,调用函数签名C,针对CPU D,使用ABI E,关于寄存器保留有什么保证?”那么该工具集的专家(或手册)可以回答。
正如您可能推断出的那样,对于任何工业级项目来说,这都是错误的问题,因为随着编译器的演变,答案将会改变,而您不希望这个事实影响您程序的可靠性。
这是一个好问题,因为了解编译器在幕后所做的事情很有助于学习。
但总的来说,黄金法则是在您的程序中表达清晰简单的逻辑,并允许编译器处理将该逻辑转化为优化机器代码的细节,现代编译器在这方面非常出色。

不仅仅是编译器,更多的是语言、架构/CPU和操作系统。对于某些架构,存在多个ABI(例如ARM、x86 - 取决于Windows或Linux(OS-X?))。 - too honest for this site
@Olaf 确实如此,我的意思是让“编译器”这个术语涵盖所有内容,但我会在答案中明确说明。 - Richard Hodges
你的描述太泛了...如果我在Windows x86架构上使用C调用约定声明一个名为foo()的函数,那么...无论编译器版本(或其选项)如何,我都知道会发生什么。如果不是这样,你甚至无法调用操作系统库函数。 - Adriano Repetti
@AdrianoRepetti 是的...除了上次我在Windows上使用Microsoft编译器时,同一程序中可以使用3种调用约定...stdcall、fastcall和其他什么(Pascal?)。请原谅我,自从我用视觉恐怖秀弄脏自己以来已经有一段时间了 :) - Richard Hodges

2
编译器生成的汇编代码遵循某些调用约定。调用约定通常规定:
  • 参数如何传递到函数
  • 被调用函数如何将返回值传递给调用者
  • 哪些寄存器应在函数调用中保存,哪些可以被修改
如果所有被调用的函数都遵循相同的调用约定,则使用相同的寄存器不应出现问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接