有时函数不使用参数(也许是因为另一个" 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将认为它必须保留会损害注册分配的输出值。