2010-03-31 10 views
49

Nel seguente codice assembly che ho buttato utilizzando objdump:Che cos'è il registro% eiz?

lea 0x0(%esi,%eiz,1),%esi 

cosa è registrare %eiz? Cosa significa il codice precedente?

+1

È possibile trovare http://sourceware.org/ml/binutils/2009-01/msg00081.html interessante. –

risposta

51

Vedi Why Does GCC LEA EIZ?:

Apparentemente %eiz è una pseudo-Register che appena viene valutata a zero in ogni momento (come r0 su MIPS).

...

alla fine ho trovato un elenco postale di spedizione dai binutils guru Ian Lance Taylor che rivela la risposta. A volte GCC inserisce istruzioni NOP nel flusso del codice per garantire un allineamento corretto e cose del genere. L'istruzione NOP richiede un byte, quindi potresti pensare di aggiungere solo il numero necessario. Ma secondo Ian Lance Taylor, è più veloce per il chip eseguire una lunga istruzione rispetto a molte brevi istruzioni. Quindi, anziché inserire sette istruzioni NOP, usano invece un LEA bizarro, che utilizza fino a sette byte ed è semanticamente equivalente a un NOP.

+2

Smart People :) Grazie per la risposta! quindi il codice sopra è solo una versione più lunga di nop: P – Heartinpiece

21

(Molto tardi al gioco, ma questa sembrava un'aggiunta interessante): Non è affatto un registro, è un capriccio della codifica delle istruzioni Intel. Quando si utilizza un byte ModRM per caricare dalla memoria, ci sono 3 bit utilizzati per il campo di registro per memorizzare 8 registri possibili. Ma il punto in cui ESP (il puntatore dello stack) "sarebbe" essere viene invece interpretato dal processore come "un byte SIB segue questa istruzione" (cioè è una modalità di indirizzamento estesa, non un riferimento a ESP). Per ragioni note solo agli autori, l'assemblatore GNU ha sempre rappresentato questo "zero dove un registro sarebbe altrimenti" come un registro "% eiz". La sintassi Intel lo lascia cadere.

+1

Grazie per la condivisione :) –

12

Andy Ross fornisce molto di più del ragionamento di base, ma è sfortunatamente sbagliato o, per lo meno, confuso sui dettagli tecnici. È vero che un indirizzo effettivo di appena (%esp) non può essere codificato solo con il byte ModR/M, in quanto invece di essere decodificato come (%esp), viene utilizzato per segnalare che è incluso anche un byte SIB. Tuttavia, lo pseudo-registro %eiz non viene sempre utilizzato con un byte SIB per rappresentare che è stato utilizzato un byte SIB.

Il byte SIB (scala/indice/base) ha tre parti: l'indice (un registro come %eax o %ecx a cui viene applicata la scala), la scala (una potenza di due da 1 a 8 che il registro indice è moltiplicato per), e la base (un altro registro che viene aggiunto all'indice scalato). Questo è ciò che consente istruzioni come add %al,(%ebx,%ecx,2) (codice macchina: 00 04 4b - opcode, modr/m, sib (nota nessun registro% eiz anche se è stato utilizzato il byte SIB)) (o in sintassi Intel, "aggiungi PTR BYTE [ecx * 2 + ebx], al ").

Tuttavia, %esp non può essere utilizzato come registro indice in un byte SIB. Invece di consentire questa opzione, Intel aggiunge invece un'opzione per utilizzare il registro di base così com'è senza ridimensionamento o indicizzazione. Pertanto, per distinguere tra il caso di add %al,(%ecx) (codice macchina: 00 01 - codice, modr/m) e add %al,(%ecx) (codice macchina: 00 04 21 - opcode, modr/m, sib), viene invece utilizzata la sintassi alternativa add %al,(%ecx,%eiz,1) (o per Intel sintassi: add BYTE PTR [ecx+eiz*1],al).

E come spiegato nell'articolo collegato a da Sinan, questa istruzione specifica (lea 0x0(%esi,%eiz,1),%esi) viene semplicemente utilizzato come nop multi-byte (equivalente a esi = &*esi) in modo che una sola istruzione NOP simile deve essere eseguita invece di molteplici istruzioni nop.

Problemi correlati