Domanda

Nel seguente codice assembly che ho buttato utilizzando objdump:

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

Qual è il registro %eiz? Che cosa significa il codice precedente?

È stato utile?

Soluzione

Perché il GCC LEA EIZ :?

  

A quanto pare %eiz è uno pseudo-registrati 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 di codice al fine di garantire un corretto allineamento e cose del genere. L'istruzione NOP prende un byte, quindi si potrebbe pensare che si può solo aggiungere come molti come necessario. Ma secondo Ian Lance Taylor, è più veloce per il chip di eseguire una lunga istruzione di molti brevi istruzioni. Quindi, piuttosto che l'inserimento di sette istruzioni NOP, che invece utilizzano un LEA bizarro, che utilizza sette byte ed è semanticamente equivalente a un NOP.

Altri suggerimenti

(molto tardi per il gioco, ma questo sembrava un'aggiunta interessante): Non è un registro a tutti, si tratta di un capriccio della codifica di istruzioni Intel. Quando si utilizza un byte ModRM caricare dalla memoria, ci sono 3 bit utilizzati per il campo registro per memorizzare 8 registri possibili. Ma il punto dove ESP (stack pointer) "sarebbe stato" è invece interpretato dal processore come "un byte SIB segue questa istruzione" (cioè esso è un modo di indirizzamento esteso, non un riferimento di ESP). Per ragioni note solo agli autori, l'assemblatore GNU ha sempre rappresentato questo "zero quando un registro altrimenti sarebbe" come "% EIZ" registro. La sintassi Intel appena lo lascia cadere.

Andy Ross offre molto di più del ragionamento di fondo, ma è purtroppo sbagliato o per lo meno confuso circa i dettagli tecnici. È vero che un indirizzo effettivo di appena (%esp) non può essere codificato con il solo / M byte MODR come invece di essere decodificato come (%esp), viene utilizzato per indicare che un byte SIB è anche incluso. Tuttavia, %eiz pseudo-il registro non è sempre utilizzato con un byte SIB per rappresentare che un byte SIB è stato utilizzato.

Il byte SIB (scala / index / base) ha tre parti ad esso: l'indice (un registro come come %eax o %ecx che la scala è applicato a), la bilancia (una potenza di due da 1 a 8 che registro indice viene moltiplicato per), e la base (un altro registro che viene aggiunto all'indice scala). Questo è ciò che permette per le istruzioni, come add %al,(%ebx,%ecx,2) (codice macchina: 00 04 4b - codice operativo, Modr / m, sib (nota n registro% EIZ anche se il byte SIB è stato utilizzato)) (o nella sintassi Intel, "aggiungere BYTE PTR [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 la possibilità di utilizzare registro base come è senza incrostazioni o indicizzazione. Quindi per disambiguare tra il caso di add %al,(%ecx) (codice macchina: 00 01 - opcode, Modr / m) e add %al,(%ecx) (codice macchina: 00 04 21 - opcode, Modr / m, SIB), la sintassi add %al,(%ecx,%eiz,1) alternativo viene invece utilizzato (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 utilizzato unicamente come nop multi-byte (equivalente a esi = &*esi) in modo che una sola istruzione NOP simile deve essere eseguita invece di molteplici nop istruzioni.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top