在主要C / C ++编译器生成的代码中注册分配规则

我记得一段时间以前的一些规则(32位以前的英特尔处理器),当时很频繁(至少对我而言)必须分析C / C ++编译器生成的汇编输出(在我看来,当时是Borland / Turbo)找到性能瓶颈,并安全地将程序集例程与C / C ++代码混合。 比如将SI寄存器用于this指针,AX用于返回值,当汇编例程返回时应保留哪些寄存器等。

现在我想知道是否有更多流行的C / C ++编译器(Visual C ++,GCC,Intel ……)和处理器(Intel,ARM,…)的参考,如果没有,在哪里找到要创建的部分一。 想法?

您询问的是“应用程序二进制接口”(ABI)和调用约定。 这些通常由操作系统和库设置,并由编译器和链接器强制执行。 Google为“ABI”或“召集会议”。 一些起点来自维基百科和Debian for ARM 。

Agner Fog的“调用约定”文档总结了Windows和Linux 64和32位ABI,其中包括: http ://www.agner.org/optimize/calling_conventions.pdf。 有关寄存器使用情况的摘要,请参见第10页的表4。

个人经验中的一个警告:不要在内联汇编中嵌入关于ABI的假设。 如果在内联汇编中编写一个函数,假定特定寄存器(例如eax,rdi,rsi)中的返回和/或参数传输,则在编译器内联函数时/它将会中断。

Open Watcom C / C ++编译器支持两种调用约定,基于寄存器(默认)和基于堆栈(非常接近其他编译器使用的)。 该编译器的用户指南描述了它们,并且可以与编译器本身一起免费在线获得。 您可以在“用户指南”中找到这些主题特别有用:

  • 10.4.1使用基于寄存器的调用约定传递参数
  • 10.4.6使用基于堆栈的呼叫约定
  • 10.5基于80×87的应用程序的调用约定

好吧,今天如果开启优化,那就没有了。 但GCC允许您声明汇编指令应该使用特定变量,无论它是否在寄存器中,或者甚至强制GCC tu将该变量放入可用于您的指令的寄存器中。 您还可以声明内联汇编块为自己保留哪些寄存器(因此,如果需要,编译器应在内联块周围生成适当的保存/恢复代码)

我相信,但我不确定GCC是否将Itanium ABI用于其大部分function; 它与它使用的ABI之间的不相容性被记录在案 。