Ошибка: неверный суффикс инструкции для `cmpxchg ‘

Я пытаюсь скомпилировать код другого проекта, и я продолжаю получать Error: invalid instruction suffix for 'cmpxchg', Строка кода, на которую постоянно указывает ошибка:

inline bool CAS(long *ptr, long oldv, long newv) {
unsigned char ret;
/* Note that sete sets a 'byte' not the word */
__asm__ __volatile__ (
"  lock\n""  cmpxchgq %2,%1\n""  sete %0\n": "=q" (ret), "=m" (*ptr)
: "r" (newv), "m" (*ptr), "a" (oldv)
: "memory");
return ret;
}

Мне было интересно, если бы кто-нибудь знал, что может быть причиной ошибки и каково возможное решение?

1

Решение

Как отмечают комментаторы, проблема заключается в ‘q’ в конце cmpxchg. Ассемблеры используют символы суффикса инструкции, чтобы указать ширину в битах, когда это было бы неоднозначно.

Этот код прекрасно компилируется с gcc для 64-битной цели. Вы получаете этот вывод для вашей инструкции cmpxchgq.

f0 48 0f b1 16          lock cmpxchg %rdx,(%rsi)

Это f0 — префикс LOCK, а 48 — префикс REX.W. Реальный код операции 0f b1.

Компиляция для 32-битной цели (опция gcc -m32) вызывает ошибку суффикса.

Если вам нужен этот код для работы на 32-битной машине, у вас возникает головная боль при портировании. sizeof (long) — 8 для 64-битной машины и 4 для 32-битной для Linux. ЕСЛИ и это большая проблема, если вся программа достаточно устойчива, чтобы выдерживать ‘long’, идущий от 8 до 4 байтов, вы можете просто изменить суффикс ‘q’ на ‘l’ (это L в нижнем регистре) , Это дает вам инструкцию ‘0f b1’ в ее 32-битной форме:

 f0 0f b1 16             lock cmpxchg %edx,(%esi)

Если нет, то вы можете попытаться переписать сборку для 32-разрядной цели, чтобы использовать CMPXCHG8B, которая представляет собой другую инструкцию с другим поведением касания регистров. CMPXCHG8B не является заменой!

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]