Ошибка сборщика Linux "невозможное ограничение в asm"
Я начинаю с ассемблера под Linux. Я сохранил следующий код как testasm.c
и скомпилировал его с помощью: gcc testasm.c -otestasm
Компилятор отвечает: "невозможное ограничение в asm".
#include <stdio.h>
int main(void)
{
int foo=10,bar=15;
__asm__ __volatile__ ("addl %%ebx,%%eax"
: "=eax"(foo)
: "eax"(foo), "ebx"(bar)
: "eax"
);
printf("foo = %d", foo);
return 0;
}
Как я могу решить эту проблему?
(Я скопировал пример из здесь.)
Debian Lenny, ядро 2.6.26-2-amd64
gcc версия 4.3.2 (Debian 4.3.2-1.1)
Разрешение:
См. Принятый ответ - кажется, что предложение "изменено" больше не поддерживается.
Ответы
Ответ 1
__asm__ __volatile__ ("addl %%ebx,%%eax" : "=a"(foo) : "a"(foo), "b"(bar));
похоже, работает. Я считаю, что синтаксис ограничений регистра изменился в какой-то момент, но он не очень хорошо документирован. Мне легче писать сырую сборку и избегать хлопот.
Ответ 2
Ограничения - это одиночные буквы (возможно, с дополнительными украшениями), и вы можете указать несколько альтернатив (т.е. промежуточный операнд или регистр - "ir" ). Таким образом, ограничение "eax" означает ограничения "e" (подписанная 32-разрядная целочисленная константа), "a" (регистр eax) или "x" (любой регистр SSE). Это немного отличается от того, что означает OP... и вывод на "e" явно не имеет никакого смысла. Кроме того, если какой-либо операнд (в данном случае вход и выход) должен быть таким же, как другой, вы ссылаетесь на него с помощью ограничения числа. Нет необходимости говорить, что eax будет сбито, это выход. Вы можете ссылаться на аргументы встроенного кода на% 0,% 1,..., не нужно использовать явные имена регистров. Поэтому правильная версия для кода, как предполагалось OP, будет:
#include <stdio.h>
int main(void)
{
int foo=10, bar=15;
__asm__ __volatile__ (
"addl %2, %0"
: "=a" (foo)
: "0" (foo), "b" (bar)
);
printf("foo = %d", foo);
return 0;
}
Лучшим решением было бы позволить% 2 быть чем угодно, а% 0 - регистром (как позволяет x86, но вам нужно будет проверить свое руководство по машине):
#include <stdio.h>
int main(void)
{
int foo=10, bar=15;
__asm__ __volatile__ (
"addl %2, %0"
: "=r" (foo)
: "0" (foo), "g" (bar)
);
printf("foo = %d", foo);
return 0;
}
Ответ 3
Если вы хотите использовать многострочный, то это также сработает.
__asm__ __volatile__ (
"addl %%ebx,%%eax; \
addl %%eax, %%eax;"
: "=a"(foo)
: "a"(foo), "b"(bar)
);
'\' следует добавить для компилятора для принятия многострочной строки (инструкции).