Can I use Intel syntax of x86 assembly with GCC?

CGccAssemblyX86Inline Assembly

C Problem Overview


I want to write a small low level program. For some parts of it I will need to use assembly language, but the rest of the code will be written on C/C++.

So, if I will use GCC to mix C/C++ with assembly code, do I need to use AT&T syntax or can I use Intel syntax? Or how do you mix C/C++ and asm (intel syntax) in some other way?

I realize that maybe I don't have a choice and must use AT&T syntax, but I want to be sure..

And if there turns out to be no choice, where I can find full/official documentation about the AT&T syntax?

Thanks!

C Solutions


Solution 1 - C

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 https://stackoverflow.com/questions/38953951/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:

Solution 2 - C

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();
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHlibView Question on Stackoverflow
Solution 1 - CninjaljView Answer on Stackoverflow
Solution 2 - CZettsu TatsuyaView Answer on Stackoverflow