2010-01-22 18 views
32

Ricordo di aver visto un modo di utilizzare l'assembly inline gcc esteso per leggere un valore di registro e memorizzarlo in una variabile C. Non posso però per la vita di me ricordare come si forma l'affermazione asm. Ogni aiuto è molto apprezzato.Lettura di un valore di registro in una variabile C

+1

E come fai a sapere che cosa è in EBX quando il codice C inizia l'esecuzione? – florin

risposta

0

Non è this quello che stai cercando?

Sintassi:

asm ("fsinx %1,%0" : "=f" (result) : "f" (angle)); 
+0

Ti rendi conto che leggerà una variabile, calcolerà il seno e quindi memorizzerà il risultato in una seconda variabile. –

+0

@ Samuel: questo era solo un esempio della sintassi. –

+0

Downvoted perché questo è un esempio di come utilizzare assembly esteso in GCC, non come ottenere il valore di un registro specifico in una variabile specifica, che è ciò che l'OP chiedeva. Specificando i registri usando '% 0' e'% 1', GCC sceglierà il registro in questione per conto tuo. Non c'è alcuna garanzia che sceglierà il registro che speri. –

5

non so su gcc, ma in questo è come VS:

int data = 0; 
__asm 
{ 
    mov ebx, 30 
    mov data, ebx 
} 
cout<<data; 

In sostanza, mi sono trasferito i dati in ebx alla variabile data.

+0

solo x86, ovviamente. I compilatori Microsoft per x64 e Itanium non supportano l'assembly inline. – ephemient

+0

Penso che il montaggio verrà tradotto in mov ebx, 30 mov dword ptr [dati], ebx – Sridarshan

+2

Perché non solo "mov dati, 30'? – Houssni

17

Ecco un modo per ottenere EBX:

int main() 
{ 
    int i; 
    asm("\t movl %%ebx,%0" : "=r"(i)); 
    return i + 1; 
} 

Il risultato:

main: 
    subl $4, %esp 
    #APP 
      movl %ebx,%eax 
    #NO_APP 
    incl %eax 
    addl $4, %esp 
    ret 


Edit:

Il "= r" (i) è un vincolo di uscita, dicendo al compilatore che il primo output (% 0) è un registro che deve essere inserito nella variabile "i". A questo livello di ottimizzazione (-O5) la variabile non viene mai memorizzata in memoria, ma viene mantenuta nel registro eax, che è anche il registro del valore di ritorno.

+1

Vorrei usare il vincolo '= rm' piuttosto che' = r'. L'ottimizzatore del compilatore tenterà di scegliere il percorso migliore. Se l'assemblatore in linea si trovasse in una situazione di fame nel registro '= r' può forzarlo a generare codice meno che ottimale. '= rm' darebbe all'ottimizzatore la possibilità di usare un riferimento di memoria se fosse la scelta migliore. In questo semplice esempio non sarà un problema, ma se il codice si trova in una situazione più complessa, dare delle opzioni al compilatore potrebbe essere utile. –

2

Questo sposta il registro del puntatore dello stack nella variabile sp.

intptr_t sp; 
asm ("movl %%esp, %0" : "=r" (sp)); 

basta sostituire 'esp' con l'attuale registri che ti interessa (ma assicuratevi di non perdere il %%) e 'st' con la variabile.

28

Andando in una direzione diversa rispetto ad altre risposte finora, dal momento che non sono sicuro di quello che vuoi.

GCC Manual § 5.40 Variables in Specified Registers

register int *foo asm ("a5"); 

Qui a5 è il nome del registro che dovrebbe essere utilizzato & hellip;

Naturalmente il nome del registro è dipendente dalla CPU, ma questo non è un problema, poiché i registri specifici sono spesso utili con istruzioni esplicite sull'assemblatore (vedere Extended Asm). Entrambe queste cose richiedono generalmente che si condizioni il programma in base al tipo di CPU.

La definizione di tale variabile di registro non riserva il registro; rimane disponibile per altri usi in luoghi in cui il controllo del flusso determina che il valore della variabile non è attivo.

GCC Manual § 3.18 Options for Code Generation Conventions

-ffixed-reg

Trattare registro menzionato reg come un registro fisso; il codice generato non dovrebbe mai riferirsi ad esso (tranne forse come un puntatore dello stack, un puntatore del frame o in qualche altro ruolo fisso).

Questo può replicare la risposta di Richard in modo più semplice,

int main() { 
    register int i asm("ebx"); 
    return i + 1; 
} 

anche se questo è piuttosto insignificante, come non avete idea di cosa c'è nel registro delle ebx.

Se combinato questi due, la compilazione di questo con gcc -ffixed-ebx,

#include <stdio.h> 
register int counter asm("ebx"); 
void check(int n) { 
    if (!(n % 2 && n % 3 && n % 5)) counter++; 
} 
int main() { 
    int i; 
    counter = 0; 
    for (i = 1; i <= 100; i++) check(i); 
    printf("%d Hamming numbers between 1 and 100\n", counter); 
    return 0; 
} 

è possibile garantire che una variabile C utilizza sempre risiede in un registro per l'accesso rapido e anche non andranno colpita da un altro codice generato. (Comoda, ebx è callee-save sotto x86 usuali convenzioni di chiamata, quindi, anche se viene clobbered da chiamate ad altre funzioni compilate senza -ffixed-*, si dovrebbe ottenere restaurata troppo.)

D'altra parte, questo sicuramente non è portatile, e di solito non è un vantaggio in termini di prestazioni, poiché si limita la libertà del compilatore.

Problemi correlati