Могу ли я использовать синтаксис Intel сборки x86 с GCC?
Я хочу написать небольшую программу низкого уровня. Для некоторых его частей мне нужно будет использовать язык ассемблера, но остальная часть кода будет написана на C/С++.
Итак, если я буду использовать GCC для смешивания C/С++ с кодом сборки, мне нужно использовать синтаксис AT & T или
Я использую синтаксис Intel? Или как вы смешиваете C/С++ и asm (синтаксис intel) каким-то другим способом?
Я понимаю, что, возможно, у меня нет выбора и должен использовать синтаксис AT & T, но я хочу быть уверенным.
И если не будет выбора, где я могу найти полную/официальную документацию о синтаксисе AT & T?
Спасибо!
Ответы
Ответ 1
Если вы используете отдельные файлы сборок, у газа есть директива для поддержки синтаксиса Intel:
.intel_syntax noprefix
который использует синтаксис Intel и не нуждается в префиксе% перед именами регистра.
Если вы используете встроенную сборку, вы можете скомпилировать ее с помощью -masm=intel
Используя .intel_syntax noprefix
в начале встроенного asm, а с помощью .att_syntax
можно работать, но будет разбиваться, если вы используете какие-либо ограничения m
. Ссылка на память будет все еще сгенерирована в синтаксисе AT & T.
Ответ 2
Вы можете использовать встроенную сборку с -masm = intel, как писал ninjalj, но это может вызвать ошибки при включении заголовков C/С++ с использованием встроенной сборки. Это код для воспроизведения ошибок в 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;
}
Когда я построил этот код, я получил сообщения об ошибках ниже.
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]'
Чтобы избежать этих ошибок, необходимо отделить встроенную сборку (верхнюю половину кода) от кода C/С++, которая требует boost:: future и т.п. (нижняя половина). Опция -masm = intel используется для компиляции файлов .cpp, содержащих встроенную сборку синтаксиса Intel, а не для других .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();
}