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

时间:2008-11-01 23:00:06

标签: c++ c assembly compiler-construction cpu-registers

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

现在我想知道是否有更多流行的C / C ++编译器(Visual C ++,GCC,Intel ......)和处理器(Intel,ARM,...)的参考,如果没有,在哪里可以找到碎片创造一个。想法?

5 个答案:

答案 0 :(得分:11)

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

答案 1 :(得分:4)

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

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

答案 2 :(得分:1)

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

  • 10.4.1使用基于注册的呼叫约定传递参数
  • 10.4.6使用基于堆栈的呼叫约定
  • 10.5基于80x87的应用程序的调用约定

答案 3 :(得分:0)

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

答案 4 :(得分:0)

我相信但是我不确定GCC是否使用Itanium ABI来完成其大部分功能;它与它使用的ABI之间的不兼容性是documented