【问题标题】:inline assembly in C++ function with return statement带有返回语句的 C++ 函数中的内联汇编
【发布时间】:2020-01-15 15:36:06
【问题描述】:

考虑这段代码:

#include <cstdio>

int get_value() { asm("movl $254, %eax"); }

int main() { printf("%d\n", get_value()); }

现在,如果使用g++ main.cpp 编译此代码,则会收到编译器警告(但代码仍可编译):

main.cpp: In function ‘int get_value()’:
main.cpp:3:43: warning: no return statement in function returning non-void [-Wreturn-type]
    3 | int get_value() { asm("movl $254, %eax"); }
      |                                    

As this answer 表示,如果编译器使用上述代码生成二进制文件,则所有赌注都将失败。 (返回类型为 int 的函数没有返回语句)

确实,当编译这段代码并开启优化g++ -O3 main.cpp 时,该程序会立即出现段错误。

所以我的问题是如何在符合 C++ 的 c++ 函数中从内联汇编返回,并且没有收到此警告,并且代码工作正常。

【问题讨论】:

  • 如果你想让机器代码与 C 一起使用,C++ 被设计为在抽象机器上工作。因此,在用 C 编译这些方法之后,您可以使用 extern "C" 将这些方法导入 C++。如果您忽略 C++ 的用途并使用非标准的事实,那么使用调用约定 cdecl 应该是您正在寻找的 stackoverflow.com/questions/10463960/…
  • 你不能只是从非void 函数的末尾掉下来(只有MSVC 的笨拙/糟糕的_asm{} 允许它作为一种黑客攻击)。当然,当 GCC 内联您的函数时,这会中断。另外,不要对编译器撒谎:你在不告诉它的情况下破坏了 EAX。教程见stackoverflow.com/tags/inline-assembly/info

标签: c++ gcc inline-assembly


【解决方案1】:

我相信你要做的就是声明一个虚拟变量,并使用 gcc 扩展语法输出该变量,然后您可以返回该变量。优化器应该剥离两个分配者。

https://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#s5 中进行了某种解释,可能如下所示:

#include <cstdio>

int get_value() {
  int b;
  asm("movl $254, %0;"
      : "=r"(b)
      );
  return b;
}

int main() {
  printf("%d\n", get_value());
}

【讨论】:

  • 这就解释了。您介意编辑答案以包含正确的代码吗? coliru.stacked-crooked.com/a/db7725efca004d52。谢谢。
  • 如果您使用的是扩展语法,是符合 C++ 还是特定于 GCC?
  • @Chipster 不是。正如本页所说:en.cppreference.com/w/cpp/language/asm,所有编译器对于不同的平台都有不同的约定。就我而言,我希望让它与 gcc 和 linux 一起工作,这很有效。我认为这是“实现定义”而不是“未定义的行为”,因为我的原始代码是。
  • 啊,好吧。这是有道理的。
  • 感谢“Lightness Races BY-SA 3.0”的示例。我只是在引用文档,并没有很好的示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-26
相关资源
最近更新 更多