2009-09-25 20 views
10

Estoy empezando con el ensamblador en Linux. Guarde el siguiente código como testasm.c
y lo compilé con: gcc testasm.c -otestasm
El compilador responde: "restricción imposible en 'asm'".Error del ensamblador de Linux "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 here.)

Debian Lenny, kernel 2.6.26-2-amd64
versión de gcc 4.3.2 (Debian 4.3.2-1.1)

Resolución:
Ver la respuesta aceptada: parece que la cláusula 'modificada' ya no se admite.

Respuesta

9
__asm__ __volatile__ ("addl %%ebx,%%eax" : "=a"(foo) : "a"(foo), "b"(bar)); 

parece que funciona. Creo que la sintaxis para las restricciones de registro cambió en algún momento, pero no está muy bien documentada. Me resulta más fácil escribir el ensamblaje sin procesar y evitar la molestia.

+0

Eso funciona, gracias. Parece que ya no le gusta la cláusula 'modificada', así que supongo que tendré que presionar y soltar lo que cambie. – slashmais

+2

La cláusula modificada todavía funciona; Creo que el problema es que "output" especifica implícitamente "modified" también, por lo que tener eax representado en ambos campos estaba causando el problema. –

0

Si se quiere utilizar varias líneas, a continuación, esto también trabajar ..

__asm__ __volatile__ (
     "addl %%ebx,%%eax; \ 
     addl %%eax, %%eax;" 
     : "=a"(foo) 
     : "a"(foo), "b"(bar) 
    ); 

'\' debe ser añadido para el compilador para aceptar una cadena de varias líneas (las instrucciones).

+0

Este no es un buen consejo. Está especificando los registros que se utilizarán en las listas de entrada y salida, pero aún usa registros codificados dentro del bloque de ensamblaje real. Deberías usar '% 0' y'% 1' en su lugar. –

+0

@DanielKamilKozar: La respuesta aceptada tenía todo en una sola línea. Entonces, utilicé el mismo código/similar para mostrar cómo hacerlo en multilínea. No intenté modificar los registros codificados utilizados en la respuesta original aceptada, ya que pensé que sería más fácil de entender cuando se compara la línea múltiple con la única. –

5

Las restricciones son simples letras (posiblemente con decoraciones adicionales), y puede especificar varias alternativas (es decir, un operando o registro inmediato es "ir"). Entonces la restricción "eax" significa restricciones "e" (constante entera de 32 bits con signo), "a" (registrar eax), o "x" (cualquier registro SSE). Eso es un poco diferente de lo que significaba OP ... y la salida a una "e" claramente no tiene sentido. Además, si algún operando (en este caso, una entrada y una salida) debe ser el mismo que otro, se refiere a él mediante una restricción numérica. No es necesario decir que eax será destruido, es una salida. Puede consultar los argumentos en el código en línea por% 0,% 1, ..., no es necesario utilizar nombres de registro 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, pero se tendría que consulte el manual de su 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; 
} 
Cuestiones relacionadas