【问题标题】:LLVM-GCC ASM to LLVM in XCodeXCode 中的 LLVM-GCC ASM 到 LLVM
【发布时间】:2012-11-09 02:44:06
【问题描述】:

我得到了以下 2 个定义,使用 XCode LLVM-GCC 编译器编译(和工作)就好了:

#define SAVE_STACK(v)__asm { mov v, ESP }
#define RESTORE_STACK __asm {sub ESP, s }

但是,当我将编译器更改为 Apple LLVM 时,出现以下错误:

Expected '(' after 'asm'

我将 {} 替换为 () 但这不起作用,我在谷歌上搜索该错误找不到任何有用的东西......有人吗?

【问题讨论】:

  • 您需要使用__asm__("asm code goes here"),并且需要使用AT&T assembly syntax 而不是Intel 语法(以及GCC 的extended asm syntax 用于访问命名变量)。
  • @ildjarn 或者只使用标准的 asm 关键字。此外,我认为 clang 确实有一些支持英特尔风格的内联汇编,但我找不到我认为的内容。后端确实支持生成 intel 样式的汇编文件 (-mllvm -x86-asm-syntax=intel),如果您只是让 clang 生成汇编文件 (-S),它会很乐意将您想要的 asm 语句中的任何文本插入到汇编结果中。
  • @bames53 : asm 仅支持 gnu* 模式;所有模式都支持__asm__
  • @ildjarn 啊,这只是在 C 中的情况。asm 是 ISO C++ 的一部分,clang 在任何 C++ 模式下都支持它,包括 GNU 寄存器扩展。
  • @bames53 :啊,这就是我浏览文档时得到的。谢谢,很高兴知道。 :-]

标签: c++ c llvm xcode4.5 llvm-gcc


【解决方案1】:

内联汇编的__asm {...} 样式是非标准的,clang 不支持。相反,C++ 将内联汇编语法指定为 asm("..."),请注意引号。此外,clang 使用 AT&T 汇编语法,因此需要重写宏以确保安全。

但是,一些工作一直在进行以改进对 Microsoft 的非标准汇编语法以及 Intel 风格的汇编的支持。有一个选项 -fenable-experimental-ms-inline-asm 可以启用到目前为止所做的事情,尽管我不确定它是什么时候引入的,或者您使用的 clang 版本的支持有多好。对您显示的代码的简单尝试似乎适用于来自 SVN 主干的最新版本的 clang。

#define SAVE_STACK(v)__asm { mov v, ESP }
#define RESTORE_STACK __asm {sub ESP, s }

int main() {
    int i;
    int s;
    SAVE_STACK(i);
    RESTORE_STACK;
}

clang++ tmp.cpp -fms-extensions -fenable-experimental-ms-inline-asm -S -o -

        .def     main;
        .scl    2;
        .type   32;
        .endef
        .text
        .globl  main
        .align  16, 0x90
main:                                   # @main
# BB#0:                                 # %entry
        pushq   %rax
        #APP
        .intel_syntax
        mov dword ptr [rsp + 4], ESP
        .att_syntax
        #NO_APP
        #APP
        .intel_syntax
        sub ESP, dword ptr [rsp]
        .att_syntax
        #NO_APP
        xorl    %eax, %eax
        popq    %rdx
        ret

并且命令 clang++ tmp.cpp -fms-extensions -fenable-experimental-ms-inline-asm 会生成一个可以运行的可执行文件。

它仍然会产生如下警告。

警告:不支持 MS 样式的内联汇编 [-Wmicrosoft]

【讨论】:

  • “提高对微软非标准汇编语法的支持”这句话是否暗示GCC使用的汇编语法更加标准?
  • @zneak 是的,asm("...") 语法是 C++ 标准的一部分,而 Microsoft 的 __asm { ... }; 不是。
  • 我只是查了一下,从标准来看这不是一个非常强烈的声明。 §7.4 说“asm 声明的形式为 asm-definition: asm ( string-literal ) ;asm 声明是有条件的-supported; 它的含义是实现定义的。" 所以严格来说,微软的实现唯一不标准的是它不接受字符串文字(并且有花括号),以及 GCC 的操作数和clobber列表也不符合标准格式。
  • @zneak gcc 对标准 asm 语句有一个非标准扩展,但 gcc 也接受并实际使用标准 asm("") 语句(即,没有它的扩展)。 VC++ 识别并忽略标准语法,支持完全不同的关键字和语法。更重要的是,鉴于 VC++ 的实现定义的汇编语言,VC++ 可以使用纯标准的asm 语句,甚至不需要 gcc 使用的扩展。
  • 如果它确实使用纯标准语法,则为 VC++ 编写的程序可以使用 GCC 编译并由于缺少 clobber 列表而产生不正确的结果。 asm 的标准值是无效的,因为它只是声明语法的存在,这破坏了任何互操作性的机会。这就是为什么我认为将 Microsoft 的实施作为非标准征税同时说 GCC 更合规是不公平的,特别是因为如果不使用 GCC 的非标准 ASM 操作数和 clobber 列表就无法回答这个问题。
【解决方案2】:

我在使用XCode开发环境下面的代码编译正确时遇到了问题。切换到我的 makefile 我收到以下错误消息Expected '(' after 'asm'

#define DebugBreak()  { __asm { int 3 }; }
int main(int argc, const char *argv[])
{
    DebugBreak();
}

请注意,DebugBreak() 的定义来自我在 Visual Studio 下编译的代码。

我在 make 文件中解决此问题的方法是添加参数 -fasm-blocks

CFLAGS += -std=c++11 -stdlib=libc++ -O2 -fasm-blocks

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多