我可以在 GCC 中使用 x86汇编的 Intel 语法吗?

我想写一个小的低级程序。对于它的某些部分,我将需要使用汇编语言,但其余的代码将在 C/C + + 上编写。

因此,如果我将使用 GCC 来混合 C/C + + 和汇编代码,我是否需要使用 AT & T 语法或者可以 我使用英特尔语法? 或者你如何混合 C/C + + 和 asm (英特尔语法)在其他一些方式?

我意识到,也许我没有选择,必须使用 AT & T 语法,但我想确保. 。

如果别无选择,我可以在哪里找到关于 AT & T 语法的完整/正式文档?

谢谢!

49180 次浏览

If you are using separate assembly files, gas has a directive to support Intel syntax:

.intel_syntax noprefix      # not recommended for inline asm

which uses Intel syntax and doesn't need the % prefix before register names.

(You can also run as with -msyntax=intel -mnaked-reg to have that as the default instead of att, in case you don't want to put .intel_syntax noprefix at the top of your files.)


Inline asm: compile with -masm=intel

For inline assembly, you can compile your C/C++ sources with gcc -masm=intel (See How to set gcc to use intel syntax permanently? for details.) The compiler's own asm output (which the inline asm is inserted into) will use Intel syntax, and it will substitute operands into asm template strings using Intel syntax like [rdi + 8] instead of 8(%rdi).

This works with GCC itself and ICC, but for clang only clang 14 and later.
(Not released yet, but the patch is in current trunk.)


Using .intel_syntax noprefix at the start of inline asm, and switching back with .att_syntax can work, but will break if you use any m constraints. The memory reference will still be generated in AT&T syntax. It happens to work for registers because GAS accepts %eax as a register name even in intel-noprefix mode.

Using .att_syntax at the end of an asm() statement will also break compilation with -masm=intel; in that case GCC's own asm after (and before) your template will be in Intel syntax. (Clang doesn't have that "problem"; each asm template string is local, unlike GCC where the template string truly becomes part of the text file that GCC sends to as to be assembled separately.)

Related:

You can use inline assembly with -masm=intel as ninjalj wrote, but it may cause errors when you include C/C++ headers using inline assembly. This is code to reproduce the errors on Cygwin.

sample.cpp:
#include <cstdint>
#include <iostream>
#include <boost/thread/future.hpp>


int main(int argc, char* argv[]) {
using Value = uint32_t;
Value value = 0;
asm volatile (
"mov  %0, 1\n\t"   // Intel syntax
//      "movl $1, %0\n\t"  // AT&T  syntax
:"=r"(value)::);


auto expr = [](void) -> Value { return 20; };
boost::unique_future<Value> func { boost::async(boost::launch::async, expr) };
std::cout << (value + func.get());
return 0;
}

When I built this code, I got error messages below.

g++ -E -std=c++11 -Wall -o sample.s sample.cpp
g++ -std=c++11 -Wall -masm=intel -o sample sample.cpp -lboost_system -lboost_thread
/tmp/ccuw1Qz5.s: Assembler messages:
/tmp/ccuw1Qz5.s:1022: Error: operand size mismatch for `xadd'
/tmp/ccuw1Qz5.s:1049: Error: no such instruction: `incl DWORD PTR [rax]'
/tmp/ccuw1Qz5.s:1075: Error: no such instruction: `movl DWORD PTR [rcx],%eax'
/tmp/ccuw1Qz5.s:1079: Error: no such instruction: `movl %eax,edx'
/tmp/ccuw1Qz5.s:1080: Error: no such instruction: `incl edx'
/tmp/ccuw1Qz5.s:1082: Error: no such instruction: `cmpxchgl edx,DWORD PTR [rcx]'

To avoid these errors, it needs to separate inline assembly (the upper half of the code) from C/C++ code which requires boost::future and the like (the lower half). The -masm=intel option is used to compile .cpp files that contain Intel syntax inline assembly, not to other .cpp files.

sample.hpp:
#include <cstdint>
using Value = uint32_t;
extern Value GetValue(void);


sample1.cpp: compile with -masm=intel
#include <iostream>
#include "sample.hpp"
int main(int argc, char* argv[]) {
Value value = 0;
asm volatile (
"mov  %0, 1\n\t"   // Intel syntax
:"=r"(value)::);
std::cout << (value + GetValue());
return 0;
}


sample2.cpp: compile without -masm=intel
#include <boost/thread/future.hpp>
#include "sample.hpp"
Value GetValue(void) {
auto expr = [](void) -> Value { return 20; };
boost::unique_future<Value> func { boost::async(boost::launch::async, expr) };
return func.get();
}