如何设置 gcc 永久使用 intel 语法? [英] How to set gcc to use intel syntax permanently?

查看:61
本文介绍了如何设置 gcc 永久使用 intel 语法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码,可以使用 gcc 命令 gcc ./example.c 编译.程序本身调用函数add_two",它只是将两个整数相加.要在扩展汇编指令中使用 intel 语法,我需要首先切换到 intel,然后再切换回 AT&T.根据 gcc 文档,可以使用 gcc -masm=intel ./exmaple 完全切换到 intel 语法.

I have the following code which compiles fine with the gcc command gcc ./example.c. The program itself calls the function "add_two" which simply adds two integers. To use the intel syntax within the extended assembly instructions I need to switch at first to intel and than back to AT&T. According to the gcc documentation it is possible to switch to intel syntax entirely by using gcc -masm=intel ./exmaple.

每当我尝试使用开关 -masm=intel 编译它时,它都不会编译,我不明白为什么?我已经尝试删除指令 .intel_syntax 但它仍然无法编译.

Whenever I try to compile it with the switch -masm=intel it won't compile and I don't understand why? I already tried to delete the instruction .intel_syntax but it still don't compile.

#include <stdio.h>

int add_two(int, int);

int main(){
     int src = 3;
     int dst = 5;
     printf("summe = %d 
", add_two(src, dst));
     return 0;
}

int add_two(int src, int dst){

    int sum;

    asm (
        ".intel_syntax;"  //switch to intel syntax
        "mov %0, %1;"
        "add %0, %2;"

        ".att_syntax;"  //switch to at&t syntax
        : "=r" (sum) //output
        : "r" (src), "r" (dst) //input
    );

    return sum;
}

使用gcc -masm=intel ./example.c编译上述程序的错误信息是:

The error message by compiling the above mentioned program with gcc -masm=intel ./example.c is:

tmp/ccEQGI4U.s: Assembler messages:
/tmp/ccEQGI4U.s:55: Error: junk `PTR [rbp-4]' after expression
/tmp/ccEQGI4U.s:55: Error: too many memory references for `mov'
/tmp/ccEQGI4U.s:56: Error: too many memory references for `mov' 

推荐答案

使用 -masm=intel 并且不要使用任何 .att_syntax 内联汇编中的指令. 这适用于 GCC,我认为适用于 ICC,以及您使用的任何约束.其他方法没有.

Use -masm=intel and don't use any .att_syntax directives in your inline asm. This works with GCC and I think ICC, and with any constraints you use. Other methods don't.

我认为 Clang 不支持 Intel 语法 GNU C 内联汇编.Clang 使用 Intel 语法 asm 的选项(-masm=intel 或等效的 -mllvm --x86-asm-syntax=intel)仅控制它如何打印 asm,而不是它如何组装输入 inline-asm.例如https://godbolt.org/z/8BCzp- 显示clang -masm=inteladd %0, 1 解释为 add dword ptr [1], eax.

I don't think Clang supports Intel-syntax GNU C inline asm. Clang's options to use Intel-syntax asm (-masm=intel or the equivalent -mllvm --x86-asm-syntax=intel) only control how it prints asm, not how it assembles inputs inline-asm. e.g. https://godbolt.org/z/8BCzp- shows clang -masm=intel interpreting add %0, 1 as add dword ptr [1], eax.

Clang 确实在 MSVC 风格的 asm 块中支持 Intel 语法,但这很糟糕(没有限制,因此输入/输出必须通过内存.

Clang does support Intel-syntax inside MSVC-style asm-blocks, but that's terrible (no constraints so inputs / outputs have to go through memory.

如果您使用 clang 对寄存器名称进行硬编码,则可以使用 -masm=intel.但它在 Intel 语法模式下在 mov %eax, 5 上阻塞,因此您不能让 %0 扩展为 AT&T 语法寄存器名称.

If you were hard-coding register names with clang, -masm=intel would be usable. But it chokes on mov %eax, 5 in Intel-syntax mode so you can't let %0 expand to an AT&T-syntax register name.

-masm=intel 使编译器在其 asm 输出文件的顶部使用 .intel_syntax noprefix,并在内联外部从 C 生成 asm 时使用 Intel 语法-asm 语句.在 asm 模板底部使用 .att_syntax 会破坏编译器的 asm,因此像 PTR [rbp-4] 这样的错误消息看起来像垃圾到汇编程序(期待 AT&T 语法).

-masm=intel makes the compiler use .intel_syntax noprefix at the top of its asm output file, and use Intel-syntax when generating asm from C outside your inline-asm statement. Using .att_syntax at the bottom of your asm template breaks the compiler's asm, hence the error messages like PTR [rbp-4] looking like junk to the assembler (which is expecting AT&T syntax).

mov 操作数过多"是因为在 AT&T 语法中,mov eax, ebx 是来自内存操作数的 mov(符号名称为 eax) 到内存操作数(具有符号名称 ebx)

The "too many operands for mov" is because in AT&T syntax, mov eax, ebx is a mov from a memory operand (with symbol name eax) to a memory operand (with symbol name ebx)

有些人建议在你的 asm 模板周围使用 .intel_syntax noprefix.att_syntax prefix.这有时可以工作,但这是有问题的.并且与-masm=intel的首选方法不兼容.

Some people suggest using .intel_syntax noprefix and .att_syntax prefix around your asm template. That can sometimes work but it's problematic. And incompatible with the preferred method of -masm=intel.

当编译器将操作数代入您的 asm 模板时,它会根据 -masm= 执行此操作.这对于内存操作数总是会中断(寻址模式语法完全不同).

When the compiler substitutes operands into your asm template, it will do so according to -masm=. This will always break for memory operands (the addressing-mode syntax is completely different).

即使对于寄存器,它也会与 clang 中断. Clang 的内置汇编程序在 Intel 语法模式下不接受 %eax 作为寄存器名称,并且不接受t 接受 .intel_syntax prefix(与通常与 Intel 语法一起使用的 noprefix 相反).

It will also break with clang even for registers. Clang's built-in assembler does not accept %eax as a register name in Intel-syntax mode, and doesn't accept .intel_syntax prefix (as opposed to the noprefix that's usually used with Intel-syntax).

考虑这个函数:

int foo(int x) {
    asm(".intel_syntax noprefix 
	"
        "add  %0, 1  
	"
        ".att_syntax"
         : "+r"(x)
        );
    return x;
}

它用 GCC 组装如下 (神弩):

It assembles as follows with GCC (Godbolt):

        movl    %edi, %eax
        .intel_syntax noprefix 
         add %eax, 1                    # AT&T register name in Intel syntax
        .att_syntax

三明治方法依赖于 GAS 接受 %eax 作为寄存器名称,即使在 Intel 语法模式下也是如此.来自 GNU Binutils 的 GAS 可以,但 clang 的内置汇编器不能.

The sandwich method depends on GAS accepting %eax as a register name even in Intel-syntax mode. GAS from GNU Binutils does, but clang's built-in assembler doesn't.

在 Mac 上,即使使用真正的 GCC,asm 输出也必须使用基于 clang 而不是 GNU Binutils 的 as 进行组装.

On a Mac, even using real GCC the asm output has to assemble with an as that's based on clang, not GNU Binutils.

在该源代码上使用 clang 会抱怨:

Using clang on that source code complains:

<source>:2:35: error: unknown token in expression
    asm(".intel_syntax noprefix 
	"
                                  ^
<inline asm>:2:6: note: instantiated into assembly here
        add %eax, 1
            ^

(错误信息的第一行没有很好地处理多行字符串文字.如果你使用 ; 而不是 并把总而言之,clang 错误消息效果更好,但来源一团糟.)

(The first line of the error message didn't handle the multi-line string literal very well. If you use ; instead of and put everything on one line the clang error message works better but the source is a mess.)

当编译器选择立即数时,我没有检查 "ri" 约束会发生什么;它仍然会用 $ 装饰它,但 IDK 如果 GAS 在 Intel 语法模式下也默默地忽略它.

I didn't check what happens with "ri" constraints when the compiler picks an immediate; it will still decorate it with $ but IDK if GAS silently ignores that, too, in Intel syntax mode.

PS:你的 asm 语句有一个错误:你忘记了输出操作数上的早期破坏,所以没有什么能阻止编译器为 %0 输出和 选择相同的寄存器%2 直到第二条指令才读取的输入.然后 mov 将销毁输入.

PS: your asm statement has a bug: you forgot an early-clobber on your output operand so nothing is stopping the compiler from picking the same register for the %0 output and the %2 input that you don't read until the 2nd instruction. Then mov will destroy an input.

但是使用 mov 作为 asm 模板的第一条或最后一条指令通常也是一个遗漏优化的错误.在这种情况下,您可以而且应该只使用 lea %0, [%1 + %2] 来让编译器将结果非破坏性地写入第三个寄存器.或者只是包装 add 指令(使用一个 "+r" 操作数和一个 "r",让编译器担心数据移动.) 如果它无论如何都必须从内存中加载值,它可以将它放在正确的寄存器中,这样就不需要 mov.

But using mov as the first or last instruction of an asm-template is usually also a missed-optimization bug. In this case you can and should just use lea %0, [%1 + %2] to let the compiler add with the result written to a 3rd register, non-destructively. Or just wrap the add instruction (using a "+r" operand and an "r", and let the compiler worry about data movement.) If it had to load the value from memory anyway, it can put it in the right register so no mov is needed.

PS:可以使用 GNU C 内联 asm 方言替代方案.例如

PS: it's possible to write inline asm that works with -masm=intel or att, using GNU C inline asm dialect alternatives. e.g.

void atomic_inc(int *p) {
    asm( "lock add{l $1, %0 | %0, 1}"
       : "+m" (*p)
       :: "memory"
    );
}

使用 gcc -O2 编译(-masm=att 是默认值)到

atomic_inc(int*):
    lock addl $1, (%rdi) 
    ret

或者使用 -masm=intel 来:

atomic_inc(int*):
    lock add DWORD PTR [rdi], 1
    ret

注意 AT&T 需要 l 后缀,intel 需要 dword ptr,因为内存,立即数并不意味着操作数大小.并且编译器为这两种情况填充了有效的寻址模式语法.

Notice that the l suffix is required for AT&T, and the dword ptr is required for intel, because memory, immediate doesn't imply an operand-size. And that the compiler filled in valid addressing-mode syntax for both cases.

这适用于 clang,但只有 AT&T 版本被使用过.

This works with clang, but only the AT&T version ever gets used.

这篇关于如何设置 gcc 永久使用 intel 语法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆