【问题标题】:Extended asm with goto, including an example from the gcc docs, fails to compile带有 goto 的扩展 asm,包括来自 gcc 文档的示例,无法编译
【发布时间】:2020-11-25 17:37:42
【问题描述】:

一些使用 goto 限定符的扩展汇编语句无法使用 GCC 10.1.0 进行编译。具体来说,

int foo(int count)
{
  asm goto ("dec %0; jb %l[stop]"
            : "+r" (count)
            :
            :
            : stop);
  return count;
stop:
  return 0;
}

(这是 GCC 扩展 asm 文档中的一个示例)无法编译并显示消息 expected ‘:’ before string constant。删除 "+r" (count)dec %0 可以使其编译成功,但无论我在与 goto 标签相同的 asm 语句中提供输出操作数时尝试什么,都会以同样的方式出错。

【问题讨论】:

  • dec 不修改 CF; jb 正在读取您没有告诉编译器的输入。这看起来像是一个损坏的示例,GCC 文档应该在它适用的 GCC 版本实际发布之前修复。

标签: c gcc inline-assembly goto


【解决方案1】:

您所引用的current development GCC documentation 似乎适用于 GCC 的最新主干分支,不适用于 GCC 的任何官方版本。到目前为止,GCC 的正式版本不支持带有任何输出或输入/输出约束的 asm goto。你可以在godbolt 上看到这个。最新的主干有效,但 10.2 和 10.1 无效。修复方法是等待 GCC 的下一个主要版本(版本 11.x);下载并编译最新的主干版本;修改您的内联程序集,使其不依赖任何输出或输出/输入约束。

直到最近,documentation for GCC up to version 10.x 还这么说:

asm goto 语句不能有输出。这是由于内部 编译器的限制:控制转移指令不能有 输出。如果汇编代码确实修改了任何内容,请使用“内存” clobber 强制优化器将所有寄存器值刷新到内存 并在 asm 语句之后根据需要重新加载它们。

可以在URL 找到正式版本的所有文档和当前开发文档的列表。当前的开发文档位于页面底部。经验法则是您应该查阅特定 GCC 版本的文档。我相信所有 10.x 版本的文档都和 GCC 网页上最新的 10.x 版本的文档是一样的。

最新版本的 CLANG/LLVM (11.0+) 确实支持此功能,但这也是相对较新的添加。

【讨论】:

    【解决方案2】:

    asm goto 不允许输出操作数。

    这是一个 gnu 决定。在 c-parser.c 的函数 c_parser_for_statement 中,您可以找到:

    /* For asm goto, we don't allow output operands, but reserve
    the slot for a future extension that does allow them.  */
    

    https://github.com/gcc-mirror/gcc/blob/releases/gcc-10/gcc/c/c-parser.c

    但是这种情况可能会改变,因为在主分支中不再存在此评论。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-11
      • 2020-03-12
      • 1970-01-01
      • 1970-01-01
      • 2021-02-21
      • 1970-01-01
      • 2012-10-26
      相关资源
      最近更新 更多