web-dev-qa-db-fra.com

Puis-je utiliser la syntaxe Intel de l'assemblage x86 avec GCC?

Je veux écrire un petit programme de bas niveau. Pour certaines parties, je devrai utiliser le langage d'assemblage, mais le reste du code sera écrit en C/C++.

Donc, si j'utilise GCC pour mélanger C/C++ avec du code d'assemblage, dois-je utiliser la syntaxe AT&T ou puis-je utiliser la syntaxe Intel? Ou comment mélangez-vous C/C++ et asm (syntaxe intel) d'une autre manière?

Je me rends compte que je n'ai peut-être pas le choix et que je dois utiliser la syntaxe AT&T, mais je veux en être sûr.

Et s'il s'avère qu'il n'y a pas d'autre choix, où puis-je trouver une documentation complète/officielle sur la syntaxe AT&T?

Merci!

59
Hlib

Si vous utilisez des fichiers d'assemblage distincts, gas a une directive pour prendre en charge la syntaxe Intel:

.intel_syntax noprefix

qui utilise la syntaxe Intel et n'a pas besoin du préfixe% avant les noms de registre.


Si vous utilisez un assemblage en ligne, vous pouvez compiler avec -masm=intel

En utilisant .intel_syntax noprefix au début de asm en ligne et en revenant avec .att_syntax peut fonctionner, mais cassera si vous utilisez des contraintes m. La référence mémoire sera toujours générée dans la syntaxe AT&T.

73
ninjalj

Vous pouvez utiliser l'assemblage inline avec -masm = intel comme l'a écrit ninjalj, mais cela peut provoquer des erreurs lorsque vous incluez des en-têtes C/C++ à l'aide de l'assemblage inline. Il s'agit d'un code pour reproduire les erreurs sur 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;
}

Lorsque j'ai créé ce code, j'ai reçu des messages d'erreur ci-dessous.

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]'

Pour éviter ces erreurs, il doit séparer l'assemblage inline (la moitié supérieure du code) du code C/C++ qui nécessite boost :: future et similaire (la moitié inférieure). L'option -masm = intel est utilisée pour compiler les fichiers .cpp qui contiennent l'assemblage en ligne de syntaxe Intel, et non vers d'autres fichiers .cpp.

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