c语言 - 如何使用 gcc 优化"don't care"参数?



有时函数不使用参数(也许是因为另一个" flags"参数无法启用特定功能)。

但是,您必须指定一些内容,因此通常您只放置0。但是,如果您执行此操作,并且该功能是外部的,则gcc会发出代码"真正确保"该参数设置为0

有没有办法告诉 gcc,函数的特定参数无关紧要,它可以让任何恰好在参数寄存器中的价值留下?

更新:有人询问了XY问题。这个问题背后的上下文是我想在x86_64中实现varargs函数,而无需使用编译器Varargs支持。当参数放在堆栈上时,这是最简单的,因此我将函数声明为5或6个虚拟参数,因此最后一个非vararg参数和所有vararg参数最终都放在堆栈上。这正常工作,除了显然不是最佳的 - 查看汇编代码时,很明显,gcc将所有这些参数寄存在呼叫者中为零。

请不要认真对待以下答案。问题要求黑客入侵,所以您去了。

GCC将有效地将非初始化变量的价值视为"不在乎",因此我们可以尝试利用它:

int foo(int x, int y);
int bar_1(int y) {
  int tmp = tmp;  // Suppress uninitialized warnings
  return foo(tmp, y);
}

不幸的是,我的GCC版本仍然怯ward将tmp初始化为零,但您的GCC版本可能更具侵略性:

bar_1:
.LFB0:
  .cfi_startproc
  movl  %edi, %esi
  xorl  %edi, %edi
  jmp   foo
  .cfi_endproc

另一个选项是(AB)使用内联装配将伪造的GCC伪造,以为tmp已定义(实际上不是):

int bar_2(int y) {
  int tmp;
  asm("" : "=r"(tmp));
  return foo(tmp, y);
}

使用此海湾合作委员会设法摆脱了参数初始化:

bar_2:
.LFB1:
  .cfi_startproc
  movl  %edi, %esi
  jmp   foo
  .cfi_endproc

请注意,内联ASM必须立即在函数调用之前,否则GCC将认为它必须保留会损害注册分配的输出值。

最新更新