ensamblador de error de Linux “restricción imposible en‘asm’”
-
16-09-2019 - |
Pregunta
Estoy empezando con el lenguaje ensamblador en Linux. He guardado el siguiente código como testasm.c
y compilado con: gcc testasm.c -otestasm
El compilador responde:. "Restricción imposible en‘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;
}
¿Cómo puedo resolver este problema? (He copiado el ejemplo de aquí .)
Debian Lenny, kernel 2.6.26-2-amd64
gcc versión 4.3.2 (Debian 4.3.2-1.1)
Resolución :
Ver la respuesta aceptada -. Parece que la cláusula de 'modificado' no se admite más
Solución
__asm__ __volatile__ ("addl %%ebx,%%eax" : "=a"(foo) : "a"(foo), "b"(bar));
parece funcionar. Creo que la sintaxis de las limitaciones del registro cambiada en algún momento, pero no es terriblemente bien documentado. Me resulta más fácil escribir el montaje en bruto y evitar la molestia.
Otros consejos
Las limitaciones son solo letras (posiblemente con decoraciones adicionales), y se pueden especificar varias alternativas (es decir, un operando inmediato o regístrese es "ir"). Por lo que la limitación "eax" significa limitaciones "e" (signo de 32 bits constante entera), "a" (registro EAX), o "x" (cualquier registro SSE). Esto es un poco diferente que lo que quería decir ... OP y salida a una "e" claramente no tiene ningún sentido. Además, si algún operando (en este caso una entrada y una salida) debe ser igual a otra, se refieren a ella por una restricción número. No hay necesidad de decir eax se clobbered, es una salida. Se puede hacer referencia a los argumentos en el código en línea de 0%,% 1, ..., sin necesidad de utilizar nombres de los registros explícitos. Por lo que la versión correcta del código de la forma prevista por la OP sería:
#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;
}
Una mejor solución sería permitir% 2 sea nada, y 0% de un registro (como x86 permite, sino que tendría que consultar el manual de la máquina):
#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;
}
Si se quiere utilizar varias líneas, entonces esto también va a funcionar ..
__asm__ __volatile__ (
"addl %%ebx,%%eax; \
addl %%eax, %%eax;"
: "=a"(foo)
: "a"(foo), "b"(bar)
);
'\' debe añadirse para que el compilador para aceptar una cadena de varias líneas (las instrucciones).