c++ - 让编译器在调用函数之前忽略设置参数寄存器

标签 c++ c assembly compiler-optimization calling-convention

TL;DR;我正在寻找一种标准方法来基本上告诉编译器将发生在给定寄存器中的任何内容传递给下一个函数。 p>

基本上我有一个函数int bar(int a, int b, int c)。在某些情况下 c 未使用,我希望能够在 c 未使用的情况下调用 bar 而无需修改 rdx 以任何方式。

例如,如果我有

int foo(int a, int b) { 
    int no_init; 
    return bar(a, b, no_init); 
}

我希望程序集只是:

尾声

    jmp bar

或正常通话

   call bar

注意:clang 通常会产生我正在寻找的东西。但我不确定在更复杂的功能中是否总是如此,我希望每次构建时都不必检查程序集。

GCC 产生:

尾声

    xorl %edx, %edx
    jmp bar

或正常通话

   xorl %edx, %edx
   call bar

我可以使用内联汇编获得我想要的结果,即将 foo(用于尾调用)更改为

int foo(int a, int b) {
    asm volatile("jmp bar" : : :);
    __builtin_unreachable();
}

编译成只是

   jmp bar

我了解 xorl %edx, %edx 的性能影响尽可能接近于 0,但是

我想知道是否有标准的方法来实现这一点。

也就是说,对于任何给定的情况,我都可以找到一个 hack。但这需要我每次都验证程序集。我正在寻找一种基本上可以告诉编译器“传递寄存器中发生的任何内容”的方法。

查看示例:https://godbolt.org/z/eh1vK8

编辑:设置 -O3 时会发生这种情况。

最佳答案

I am wondering if there is a standard way to achieve this.

I.e I can probably find a hack for it for any given case. But that will require me verifying the assembly each time. I am looking for a method that you can basically tell the compiler "pass whatever happened to be in register".

不,没有标准的方法可以在 C 或 C++ 中实现它。这两种语言都不涉及任何较低级别的函数调用语义,甚至不承认 CPU 寄存器的存在,* 并且这两种语言都要求每个函数调用都提供与所有非可选参数相对应的参数(只是 C 中的“所有声明的参数”)。

For example if I have

int foo(int a, int b) { 
    int no_init; 
    return bar(a, b, no_init); 
}

...然后,由于使用了不确定的 no_init 的值,您将获得 未定义的行为。无论任何特定的 C 或 C++ 实现完全接受它,它的定义都是非标准的。

如果你想调用bar(),但你不关心作为第三个参数传递什么值,那为什么不直接选择一个方便的值来传递呢?零,例如:

    return bar(a, b, 0); 

*就任一种语言标准而言,即使是 register 关键字也不这样做。

关于c++ - 让编译器在调用函数之前忽略设置参数寄存器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65646278/

相关文章:

c++ - 是否有将信号处理(c 库)映射到 c++ 异常的可能方法?

c++ - 虚幻引擎 C1083

c - 循环scanf问题,多次尝试后崩溃

assembly - 从文档文件在 Turbo C++ 3.0 中创建内联汇编代码 (TASM)

c# - 尝试在 C# 中创建基本编译器,获取访问冲突错误

c++ - 如何找到字符串列表中所有项目的公共(public)部分?

c++ - 游戏设计与程序语言和 OOP 语言的差异

c - 读取二进制文件,存入缓冲区,打印缓冲区内容

c - 如何将C移植到新架构?

windows - 如何在 16 位 MASM Assembly x86 中创建 sleep 函数?