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