2016-03-26 5 views
0

С инлайн сборки в GCC, вы можете указать непосредственный операнд ассемблера с "i" ограничения, например, так:Как использовать непосредственное ограничение с синтаксисом Intel в gcc?

void set_to_five(int* p) 
{ 
    asm 
    (
     "movl %1, (%0);" 
     :: "r" (p) 
     , "i" (5) 
    ); 
} 

int main() 
{ 
    int i; 
    set_to_five(&i); 
    assert(i == 5); 
} 

Ничего плохого с этим до сих пор, за исключением того, что это в ужасна AT & T синтаксис. Итак, давайте попробуем еще раз с .intel_syntax noprefix:

void set_to_five(int* p) 
{ 
    asm 
    (
     ".intel_syntax noprefix;" 
     "mov [%0], %1;" 
     ".att_syntax prefix;" 
     :: "r" (p) 
     , "i" (5) 
    ); 
} 

Но это не работает, так как компилятор вставляет $ префикса перед непосредственным значением, которое ассемблер больше не понимает.

Как использовать ограничение "i" с синтаксисом Intel?

+1

Попробуйте использовать '% c1' (см. Https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#x86Operandmodifiers). Кроме того, рассмотрите использование -masm = intel вместо псевдоопераций. –

+0

Я, должно быть, читал эту страницу, как 10 раз, но почему-то я пропустил этот бит. Благодаря! Вы должны опубликовать это как ответ. – user5434231

+0

И как бы я хотел использовать '-masm = intel', это вызывает проблемы при включении заголовков с синтаксисом AT & T. – user5434231

ответ

1

Вы должны иметь возможность использовать% c1 (см. modifiers).

Обратите внимание, что если вы используете символические имена (которые мне легче читать/поддерживать), вы можете использовать% c [five].

Наконец, я понимаю код, это просто «для экземпляра», но вы изменяете память, не сообщая компилятору. Это «плохо». Рассмотрите либо использование ограничения вывода для памяти ("=m"), либо добавление «клонирования» памяти.

+0

Возникает второй вопрос; следует ли использовать '' память ''clobber для побочных эффектов без памяти (например, доступ к порту ввода/вывода)? – user5434231

+0

Точка памяти clobber должна позволить компилятору узнать, будет ли ваш asm читать память «кроме тех, которые указаны в входных и выходных операндах». Это позволяет компилятору знать, что если он имеет какие-либо значения, кэшированные в регистрах, они должны быть сброшены в память перед/перезагрузкой послесловия. Если операция ввода-вывода действительно «не является памятью» (т. Е. Не записывает блок памяти на диск, читает блок с диска и т. Д.), Тогда (возможно, нет) компилятору. Трудно сказать абсолютно без специфики. –

+0

Я думал об аппаратных портах ввода/вывода (инструкции 'in' /' out'). Эти вещи не хранятся в переменных C/C++, поэтому я не предполагаю, что здесь потребуется «память», просто «asm volatile», чтобы убедиться, что они выполнены в правильном порядке. – user5434231