C编译器是否优化汇编中的函数,以使对堆栈的使用最小化?

兰斯·波拉德

我开始学习汇编(在OSX上的NASM中为x86-64),现在正在探索函数的外观。

解释“调用约定”工作原理的大多数资源都按照以下方式显示示例:

// c code
MyFunction1(a, b);

// assembly code
main:
  push a
  push b
  push rbp ; save frame pointer on stack
  mov rsp, rbp  ; save stack pointer in frame pointer
  xor rax, rax  ; set function return value to 0.
  call _MyFunction
  mov rbp, rsp  ; restore stack pointer
  pop rbp ; restore frame pointer
  ret ; return to calling function

我只是在合并了几种资源之后才做出的,所以可能有很多问题,但这不在主要问题之列。

诸如cdecl调用约定之类的调用约定的要旨是:

  • 您以与在C代码中出现的方式相反的顺序推入参数。
  • 然后,您可以保存对框架指针和堆栈指针的引用(我猜是这样,您可以递归地执行此操作,但到目前为止还不知道)。
  • 然后,您可以计算出函数中所需的一切。
  • 然后,弹出堆栈,并从堆栈中弹出框架指针

因此,希望获得在汇编中使用堆栈和函数调用约定的更多实践经验,我希望看到现有的C编译器如何将函数调用转换为汇编(gcc和clang,非常有用)。但是,我没有看到调用约定模式(到目前为止,我所见过的每个资源都说过这是做到这一点的方法)!

检查一下,这是从某些C生成的相对复杂的汇编代码:

https://gist.github.com/lancejpollard/a1d6a9b4820473ed8797

查看该C代码,有几个层次的嵌套函数调用。但是输出程序集代码未显示该推/弹出堆栈模式!

所以问题是,这些编译器是否只是为了优化汇编程序而避免这样做?(因为该示例C代码虽然具有一些嵌套函数,但仍然非常简单,因此我认为编译器可以预先计算很多东西)。还是我错过了什么?

布伦丹

一般来说:

  • 如果某个函数可能被另一个目标文件中的某个东西调用(例如,该函数不是,static而您正在创建一个目标文件),则编译器必须遵守调用约定(以便链接可以工作)。
  • 如果您要进行调试编译,那么典型的调试器将使用堆栈框架查找内容(输入参数,局部变量等),并且性能并不是优先考虑的事情,因此遵守调用约定是一个好主意。

对于所有其他情况,编译器可以自由地完全忽略调用约定,并且可以做任何它认为更有效的事情(包括在寄存器中传递参数,而不使用堆栈或帧指针,还包括完全内联函数)。

然而:

  • 在某些情况下(例如,函数指针和具有可变数量的参数的函数),编译器可能无法做很多事情,并且可能仅使用标准的调用约定(即使严格不需要)。
  • 编译器可能会生成2个或更多不同版本的函数(例如,一个遵循其他对象文件中的代码可以使用的调用约定的版本,以及另一个不遵循调用约定的优化版本)。
  • 链接器可能会优化编译器无法进行的优化(链接时间优化),包括修改编译器无法优化的函数的调用约定(因为编译器对潜在调用者的了解不足),但是链接器可以(因为链接程序“看到”整个程序)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

编译器可以优化汇编中的函数序言吗?

在连续调用函数的情况下,C编译器是否优化执行堆栈?

您可以使用 C 内联汇编来对齐指令吗?(没有编译器优化)

编译器是否在析构函数中优化memset?

C ++编译器是否优化重复的函数调用?

是否允许C编译器优化未使用的函数参数?

虚拟函数编译器优化C ++

优化问题 - 最小化 R 中的函数

C++ 编译器是否对齐小函数以优化缓存行提取?

是否对不使用模板参数的模板化类的方法进行了编译器优化?

是否可以使用.NET Core Roslyn编译器编译单个C#代码文件?

是否可以使用C#编译器添加PostSharp进行动态编译

BCC中的内联汇编(Bruce的C编译器)-如何使用C变量?

C#JIT编译器是否优化空检查?

C++ 编译器是否优化了已知语句?

是否允许C编译器优化掉多余的语句?

C#编译器是否在优化可空类型?

编译器是否优化未使用的参数?

使用函数中的malloc创建的Char *,编译器表示地址在堆栈上,无法返回

F#编译器是否以与C#编译器相同的方式支持foreach优化

C#编译器或JIT是否可以优化Lambda表达式中的方法调用?

确定C ++编译器是否将在Visual Studio中以某种方式进行优化

使用列表初始化时,C ++语言是否会强制执行编译器优化?

C ++编译器是否通常会“优化” malloc,并免费使用new和delete?

为什么编译器未使用-O3优化此C ++成员函数?

C编译器编译的C源代码中可以使用static_cast吗?

编译器设计中的内联汇编

C / C ++优化编译器由于使用模板而损坏

编译器是否优化变量声明?