2012-02-19 10 views
48

Chcę napisać mały program niskiego poziomu. Dla niektórych jego części będę musiał używać języka asemblera, ale reszta kodu będzie napisana w C/C++.Czy mogę użyć składni Intel zestawu x86 z GCC?

Tak więc, jeśli użyję GCC mieszać C/C++ z kodem montażu, muszę użyć składni AT & T lub mogą używam składni Intel? Lub w jaki sposób mieszać C/C++ i ASM (składnię intel) w inny sposób?

Zdaję sobie sprawę, że może nie mają wyboru i muszą korzystać z AT & składni T, ale chcę mieć pewność ..

A jeśli okaże się, że nie ma wyboru, gdzie mogę znaleźć pełny/oficjalna dokumentacja dotycząca składni AT & T?

Dzięki!

+0

Jeśli napiszesz całe funkcje w ASM, mogą być one w osobnym pliku skompilowanym. Jeśli nie masz nic przeciwko zależnościom od YASM lub NASM, możesz łatwo użyć dowolnej składni. (Ale wtedy twój asm musi radzić sobie z różnymi ABI dla Windows i Linuxa, może z makrami asemblera.) [Instrukcja GNU asemblera jest w trybie online] (https://sourceware.org/binutils/docs/as/), a także zwykle instalowane z gcc/binutils. ('info as'). –

+0

Uważaj na składnię Intela, ponieważ dławiki Clang są zintegrowane z dławikiem asemblera. Zobacz także [Wydanie LLVM 24232: argumenty operacji wbudowanych nie działają z .intel_syntax] (http://llvm.org/bugs/show_bug.cgi?id=24232). Raport o błędzie pokazuje, że Clang ma problem z prostą negacją. – jww

Odpowiedz

61

Jeśli używasz oddzielne pliki montaż, gaz ma dyrektywę wspierania Intel składni:

.intel_syntax noprefix 

który wykorzystuje składnię Intel i nie potrzebuje% prefiksu przed nazwami rejestrów.


Jeśli używasz zestawu inline, można skompilować z -masm=intel

Korzystanie .intel_syntax noprefix na początku inline ASM, i przełączenie z powrotem .att_syntax może pracować, ale złamie jeśli użyć dowolnego m ograniczenia. Odwołanie do pamięci nadal będzie generowane w składni AT & T.

+1

Dziękuję, ninjalj !!!!!! – Hlib

+12

Nie zapomnij zwrócić standardu AT & T na końcu sekcji montażowej. '.att_syntax noprefix' robi to. Poza tym asembler spróbuje zinterpretować wygenerowany przez kompilator kod zespołu, który jest w formacie AT & T, jako format Intela. – ugoren

+7

@ugoren: '-masm = intel' powoduje, że kompilator generuje składnię Intela.Naprawdę potrzebujesz tego do wbudowanego zestawu, w przeciwnym razie '' m "' ograniczenia pamięci nie będą działać. – ninjalj

4

Możesz użyć wbudowanego zestawu z -masm = intel, jak napisał ninjalj, ale może to spowodować błędy podczas dołączania nagłówków C/C++ za pomocą wbudowanego zestawu. To jest kod do odtworzenia błędów na Cygwin.

Kiedy zbudowałem ten kod, otrzymałem poniżej komunikaty o błędach.

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

Aby uniknąć tych błędów, musi oddzielić montaż inline (górna połowa kodu) z C/C++ kod, który wymaga boost :: przyszłości i tym podobne (dolna połowa). Opcja -masm = intel służy do kompilowania plików .cpp, które zawierają składnię wbudowaną składni Intel, a nie do innych plików .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(); 
} 
Powiązane problemy