2009-09-25 33 views
10

Inizio con l'assemblatore sotto Linux. Ho salvato il seguente codice come testasm.c
e lo ho compilato con: gcc testasm.c -otestasm
Il compilatore risponde: "impossibile vincolo in 'asm'".Errore di assemblatore Linux "vincolo impossibile in '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; 
} 

Come posso risolvere questo problema? (Ho copiato l'esempio da here.)

Debian Lenny, kernel 2.6.26-2-amd64
versione di gcc 4.3.2 (Debian 4.3.2-1.1)

Risoluzione:
Vedere la risposta accettata - sembra che la clausola 'modificata' non sia più supportata.

risposta

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

sembra funzionare. Credo che la sintassi per i vincoli del registro sia cambiata a un certo punto, ma non è molto ben documentata. Trovo più facile scrivere assembly raw ed evitare il fastidio.

+0

Funziona, grazie. Sembra che non piaccia più la clausola 'modificata', quindi suppongo che dovrò spingere e popl qualunque cosa cambi. – slashmais

+2

La clausola modificata funziona ancora; Penso che il problema sia che "output" specifica implicitamente anche "modificato", quindi avere il eax rappresentato in entrambi i campi stava causando il problema. –

0

Se si vuole usare più righe, allora questo funziona anche ..

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

'\' deve essere aggiunto per il compilatore di accettare una stringa multilinea (le istruzioni).

+0

Questo non è un buon consiglio. Stai specificando i registri da utilizzare negli elenchi di input e output, ma continui a utilizzare i registri hardcoded all'interno del blocco di assiemi effettivo. Dovresti usare '% 0' e'% 1' invece. –

+0

@DanielKamilKozar: la risposta accettata aveva tutto in un'unica riga. Quindi, ho usato lo stesso codice/simile per mostrare come farlo in multilinea. Non ho provato a modificare i registri hardcoded usati nella risposta originale accettata, poiché pensavo che fosse più facile capire quando si confronta la multi linea con la singola. –

5

I vincoli sono lettere singole (eventualmente con decorazioni aggiuntive) e è possibile specificare diverse alternative (ad esempio, un operando intermedio o il registro è "ir"). Quindi il vincolo "eax" significa vincoli "e" (costante a 32 bit con segno), "a" (registro eax) o "x" (qualsiasi registro SSE). Questo è un po 'diverso dal fatto che ciò che OP significava ... e output in una "e" chiaramente non ha alcun senso. Inoltre, se alcuni operandi (in questo caso un input e un output) devono essere uguali a un altro, ci si riferisce ad esso tramite un vincolo numerico. Non c'è bisogno di dire che l'eax sarà bocciato, è un'uscita. È possibile fare riferimento agli argomenti nel codice inline di% 0,% 1, ..., non è necessario utilizzare nomi di registro espliciti. Così la versione corretta per il codice come previsto dal PO sarebbe:

#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 soluzione migliore sarebbe quella di permettere% 2 di essere qualsiasi cosa, e% 0 un registro (come x86 consente, ma che avrebbe dovuto controllare il manuale della macchina):

#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; 
} 
Problemi correlati