Domanda

Stavo leggendo il Manuale di istruzioni Intel e notato che c'è un'istruzione" NOP "che non fa nulla sulla CPU principale e un'istruzione" FNOP "Non fa nulla sulla FPU.Perché ci sono due istruzioni separate per non fare nulla?

L'unica cosa diversa che ho visto è che lanciano diverse eccezioni, quindi potresti vedere un'eccezione da FNOP per rilevare se c'è una FPU disponibile.Ma non ci sono altri meccanismi come CPUID per rilevare questo?Quale motivo pratico è lì per avere due istruzioni NOP separate?

È stato utile?

Soluzione

Esaminando i commenti dei Raymond Chen e di Hans Passionan, ci sono motivi storici per esserci due istruzioni separate e perché non hanno lo stesso effetto.

Nessuna delle due istruzioni, NOP e FNOP, sono state originariamente progettate come un'istruzione esplicita senza funzionamento. L'istruzione NOP è in realtà solo un alias per l'istruzione XCHG AX,AX. (O in modalità a 32 bit XCHG EAX, EAX.) I primi processori Intel non effettivamente non fare nulla. Mentre non aveva effetto esternamente visibile, internamente è stato eseguito come un'istruzione XCHG, prendendo tanti cicli da eseguire. La '486 è stata la prima CPU Intel per trattarla appositamente, potrebbe eseguire un NOP in 1 ciclo, mentre ci sono voluti 3 cicli per eseguire qualsiasi altra istruzione XCHG di registrazione per registrare.

Trattare l'istruzione XCHG AX,AX diventa particolarmente importante nei moderni processori Intel. Se stavi ancora scambiando lo stesso registro con se stesso, potrebbe introdurre bancarelle di pipeline se un'istruzione nelle vicinanze utilizzava anche il registro AX. Trattandolo in particolare la CPU non finisce per pensare che il NOP deve attendere un'assistenza precedente che imposta AX o che un'istruzione seguente deve attendere il NOP.

Questo porta il fatto che ci sono molte istruzioni diverse che non fanno nulla, anche se XCHG AX,AX è l'unico che è un singolo byte (come caso speciale del Exchange-registrazione-con-accumulatore singolo byte XCHG Encordings ). Spesso queste istruzioni vengono utilizzate come sostituto dell'istruzione singola per le istruzioni consecutive NOP, come quando si allinea l'inizio del loop per motivi di prestazioni. Ad esempio se volevi un NOP 6 Byte puoi usare LEA EAX,[EAX + 00000000]. Alla fine Intel ha aggiunto un'istruzione esplicita byte multipla. (Bene, non tanto aggiunto come documentato ufficialmente un'istruzione che era stata lì da Pentium Pro.) Tuttavia solo il modulo singolo dei byte viene trattato appositamente; I multipli nop byte genereranno bancarelle se le istruzioni nelle vicinanze utilizzano gli stessi registri.

Quando AMD ha aggiunto il supporto a 64 bit alle proprie CPU è andato ancora oltre. NOP non è più l'equivalente di XCHG EAX,EAX in modalità a 64 bit. Uno dei problemi con il set di istruzioni Intel è che ci sono molte istruzioni che modificano solo parte del registro. Ad esempio MOV BX,AX modifica solo i 16 bit più bassi del EBX lasciando i 16 bit superiori non modificati. Queste modifiche parziali rendono difficile per la CPU evita le bancarelle, quindi AMD decide di impedire che quando si usano le istruzioni a 32 bit in modalità a 64 bit. Ogni volta che il risultato di un'operazione a 32 bit viene memorizzata in un registro (64 bit), Il valore è zero esteso a 64 bit in modo che l'intero registro sia modificato . Ciò significa che XCHG EAX,EAX non è più un NOP, poiché cancella i 32 bit superiori di EAX (e quindi se si scrive esplicitamente XCHG EAX,EAX, non può assemblare a 0x90 e deve utilizzare la codifica 87 C0). In modalità a 64 bit NOP è ora un NOP esplicito senza altra interpretazione. .


.

Per quanto riguarda l'istruzione FNOP, sull'originale 8087 non è completamente chiaro come la FPU ha trattato questa istruzione, ma sono abbastanza sicuro che non sia stato gestito come nessuna operazione esplicita. Almeno un vecchio manuale Intel, il ASM86 Language Rerefence Manual Documenta il documento come fare qualcosa senza alcun effetto ("memorizza la parte superiore della pila alla parte superiore dello stack"). Dalla sua posizione nella mappa dell'OPCODE sembra che possa un alias per FST ST o FLD STTagCode, entrambi copiare la parte superiore dello stack nella parte superiore della pila. Tuttavia ha ottenuto un trattamento speciale, ha eseguito in una media di 13 cicli invece dei cicli medi da 18 o 20 per uno stack per impilare rispettivamente l'istruzione FST o FLD. Se fosse stato trattato come istruzione senza funzionamento, mi aspetterei ancora più veloce, poiché ci sono un certo numero di istruzioni 8087 che possono eseguire a metà tempo.

Ancora più importante L'istruzione FNOP si comporta in modo diverso rispetto al NOP a causa del modo in cui le istruzioni FPU utilizzate per essere implementate sui processori Intel. La stessa CPU non ha supportato l'aritmetica a punto flottante, invece questi doveri furono scaricati su un coprocessore flottante opzionale, originariamente il

8087. Una delle cose belle del coprocessore era che ha eseguito le istruzioni in parallelo con la CPU. Tuttavia ciò significa che la CPU a volte deve attendere che la FPU finisca un'operazione. La CPU attende automaticamente per finire l'esecuzione delle istruzioni precedenti prima di dargli un'altra istruzione, ma un programma avrebbe dovuto aspettare esplicitamente (utilizzando un'istruzione WAIT) prima che possa leggere un risultato che il coprocessore ha scritto alla memoria.

Poiché il coprocessore ha lavorato in parallelo, questo significava anche che se un'istruzione FPU ha generato un'eccezione flottante, nel momento in cui ha rilevato che la CPU si sarebbe già spostata per eseguire le istruzioni successive. Normalmente quando un'istruzione genera un'eccezione sulla CPU, viene gestita mentre tale istruzione viene ancora eseguita, ma quando un'istruzione FPU genera un'eccezione, la CPU ha già completato l'esecuzione dell'istruzione consegnandolo alla FPU. Invece di interrompere la CPU e fornire l'eccezione a punto flottantemente, la CPU viene avvisata solo quando attende il coprocessore, esplicitamente o implicitamente.

Nei processori moderni la FPU non è più un coprocessore, è parte integrante della CPU. Ciò significa che i programmi non devono più attendere che la FPU scrivere valori in memoria. Tuttavia, il modo in cui le eccezioni della FPU sono gestite non sono cambiate. (Si scopre che offrendo le eccezioni immediatamente è difficile da implementare sulle CPU moderne in modo da approfittare del caso in cui non hanno dovuto.) Quindi se un'istruzione FPU precedente ha generato un'eccezione flottante non consegnata, un NOP lascia il Eccezione non consegnata, mentre FNOP, perché è un'istruzione FPU, farà un "attesa" implicito che si traduce nell'eccezione del punto flottante consegnato.

Questo esempio dimostra la differenza:

FLD1       ; push 1.0 onto the FPU stack
FLDZ       ; push 0.0
FDIV       ; divide 1.0 by 0.0
NOP        ; does nothing
NOP        ; does nothing
FNOP       ; signals a FP zero-divide exception and then does nothing
.

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