Domanda

% AX = (% AH +% AL)

Quindi perché non % EAX = (% SOME_REGISTER +% AX) per alcuni registri % SOME_REGISTER ?

È stato utile?

Soluzione

Solo per qualche chiarimento. Nei primi giorni del microprocessore degli anni '70, le CPU avevano solo un piccolo numero di registri e un set di istruzioni molto limitato. Tipicamente, l'unità aritmetica poteva funzionare solo su un singolo registro CPU, spesso indicato come "accumulatore". L'accumulatore sull'8080 a 8 bit e amp; I processori Z80 erano chiamati "A". C'erano altri 6 registri a 8 bit per uso generale: B, C, D, E, H & amp; L. Questi sei registri possono essere accoppiati per formare 3 registri a 16 bit: BC, DE & amp; HL. Internamente, l'accumulatore è stato combinato con il registro Flags per formare il registro AF a 16 bit.

Quando Intel ha sviluppato la famiglia 8086 a 16 bit, voleva essere in grado di trasferire il codice 8080, quindi ha mantenuto la stessa struttura di registro di base:

8080/Z80  8086
A         AX
BC        BX
DE        CX
HL        DX
IX        SI    
IY        DI

A causa della necessità di portare il codice a 8 bit, dovevano essere in grado di fare riferimento alle singole parti a 8 bit di AX, BX, CX & amp; DX. Questi sono chiamati AL, AH per il basso & amp; byte elevati di AX e così via per BL / BH, CL / CH e amp; DL / DH. IX & amp; IY sullo Z80 veniva usato solo come registri puntatore a 16 bit, quindi non era necessario accedere alle due metà di SI & amp; DI.

Quando l'80386 fu pubblicato a metà degli anni '80, crearono "esteso" versioni di tutti i registri. Quindi, AX è diventato EAX, BX è diventato EBX ecc. Non è stato necessario accedere ai primi 16 bit di questi nuovi registri estesi, quindi non hanno creato uno pseudo registro EAXH.

AMD ha applicato lo stesso trucco quando hanno prodotto i primi processori a 64 bit. La versione a 64 bit del registro AX si chiama RAX. Quindi, ora hai qualcosa che assomiglia a questo:

|63..32|31..16|15-8|7-0|
               |AH.|AL.|
               |AX.....|
       |EAX............|
|RAX...................|

Altri suggerimenti

Ci sono molte risposte pubblicate qui, ma nessuna risponde davvero alla domanda data: Perché non esiste un registro che codifica direttamente i 16 bit alti di EAX o i 32 bit alti di RAX? La risposta si riduce ai limiti dell'istruzione x86 che codifica se stessa.

Lezione di storia a 16 bit

Quando Intel progettò l'8086, usarono uno schema di codifica a lunghezza variabile per molte delle istruzioni. Ciò significava che alcune istruzioni estremamente comuni, come POP AX , potevano essere rappresentate come un singolo byte (58), mentre istruzioni rare (ma ancora potenzialmente utili) come MOV CX, [BX * 4 + BP + 1023] potrebbe ancora essere rappresentato, anche se siano necessari diversi byte per memorizzarli (in questo esempio, 8B 8C FF 03).

Potrebbe sembrare una soluzione ragionevole, ma quando lo hanno progettato, hanno riempito la maggior parte dello spazio disponibile . Quindi, ad esempio, c'erano otto istruzioni POP per gli otto singoli registri (AX, CX, DX, BX, SP, BP, SI, DI) e hanno compilato i codici operativi da 58 a 5F, e opcode 60 era qualcos'altro ( PUSHA ), così come opcode 57 ( PUSH DI ). Non c'è più spazio per nulla dopo o prima di quelli. Anche spingendo e facendo scoppiare i registri di segmento & # 8212; che è concettualmente quasi identico a spingere e fare scoppiare i registri di uso generale & # 8212; doveva essere codificato in una posizione diversa (verso il basso intorno a 06 / 0E / 16 / 1E) solo perché non c'era spazio accanto al resto delle istruzioni push / pop.

Allo stesso modo, il " mod r / m " byte utilizzato per un'istruzione complessa come MOV CX, [BX * 4 + BP + 1023] ha solo tre bit per codificare il registro, il che significa che può rappresentare solo otto registri in totale. Va bene se hai solo otto registri, ma presenta un vero problema se vuoi averne di più.

(C'è un'eccellente mappa di tutte queste allocazioni di byte nell'architettura x86 qui: http://i.imgur.com/xfeWv .png . Nota come nella mappa principale non sia rimasto spazio, con alcune istruzioni che si sovrappongono ai byte e persino quanto della mappa secondaria "0F" viene ora utilizzata grazie alle istruzioni MMX e SSE.)

Verso 32 e 64 bit

Quindi, anche per consentire l'estensione della progettazione della CPU da 16 bit a 32 bit, avevano già un problema di progettazione e l'hanno risolto con prefisso byte : aggiungendo uno speciale " 66 " byte davanti a tutte le istruzioni standard a 16 bit, la CPU sa che si desidera la stessa istruzione ma la versione a 32 bit (EAX) invece della versione a 16 bit (AX). Il resto del design è rimasto lo stesso: nell'architettura complessiva della CPU c'erano solo otto registri di uso generale.

Un hacker simile doveva essere fatto per estendere l'architettura a 64 bit (RAX e amici); lì, il problema è stato risolto aggiungendo l'ennesimo set di prefissi ( REX , 40-4F) che significava "a 64 bit". (e ha effettivamente aggiunto altri due bit al campo "mod r / m"), e scartando anche strane vecchie istruzioni che nessuno ha mai usato e riutilizzando i loro codici byte per cose nuove.

A parte i registri a 8 bit

Una delle domande più grandi da porre, quindi, è come diavolo le cose come AH e AL abbiano mai funzionato in primo luogo se c'è davvero spazio nella progettazione per otto registri. La prima parte della risposta è che non esiste nulla come " PUSH AL " & # 8212; alcune istruzioni semplicemente non possono funzionare sui registri di dimensioni in byte! Le uniche che possono essere alcune stranezze speciali (come AAD e XLAT ) e versioni speciali di " mod r / m " istruzioni: facendo capovolgere un bit molto specifico in & mod; mod r / m " byte, quelle "istruzioni estese" potrebbe essere invertito per operare sui registri a 8 bit anziché su quelli a 16 bit. Accade solo che ci siano esattamente otto registri a 8 bit: AL, CL, DL, BL, AH, CH, DH e BH (in quell'ordine), e questo si allinea molto bene con gli otto slot di registro disponibili nel "mod r / m" Byte.

Intel notò all'epoca che il design dell'8086 doveva essere "compatibile con la sorgente" con l'8080/8085: c'era un'istruzione equivalente nell'8086 per ciascuna delle istruzioni 8080/8085, ma non utilizzava gli stessi codici byte (non sono nemmeno vicini) e dovresti ricompilare ( riassemblare) il programma per farlo utilizzare i nuovi codici byte. Ma "compatibile con la fonte" era una strada da percorrere per il vecchio software, e consentiva ai singoli dell'8085 A, B, C, ecc. e la combinazione "BC" e " DE " registra di funzionare ancora sul nuovo processore, anche se ora erano chiamati "AL" e "BL" e "BX" e "DX" (o qualunque fosse la mappatura).

Quindi questa è davvero la vera risposta: non è che Intel o AMD abbiano intenzionalmente escluso " un registro alto a 16 bit per EAX o un registro alto a 32 bit per RAX: è che i registri alti a 8 bit sono una strana anomalia storica residua e replicare il loro design a dimensioni di bit più elevate sarebbe davvero difficile dato il requisito che l'architettura è compatibile con le versioni precedenti.

Considerazioni sul rendimento

C'è un'altra considerazione sul perché quei "registri alti" non sono stati aggiunti da allora: anche all'interno delle architetture di processori moderne, per motivi di prestazioni, i registri di dimensioni variabili non si sovrappongono realmente: AH e AL non fanno parte di AX e AX non fa parte di EAX ed EAX non fanno parte di RAX: sono tutti registri separati sotto il cofano e il processore imposta un flag di invalidazione sugli altri quando ne manipoli uno in modo che sappia che dovrà copiare i dati quando hai letto dagli altri.

(Ad esempio: se si imposta AL = 5, il processore non aggiorna AX. Ma se poi si legge da AX, il processore copia rapidamente quel 5 da AL nei bit inferiori di AX.)

Mantenendo separati i registri, la CPU può fare ogni sorta di cose intelligenti come la ridenominazione invisibile dei registri per rendere il tuo codice più veloce, ma ciò significa che il tuo codice verrà eseguito più lento se usi il vecchio modello di trattamento dei piccoli registri come pezzi di registri più grandi, poiché il processore dovrà arrestarsi e aggiornarli. Per evitare che tutta questa contabilità interna sfugga di mano, i progettisti della CPU hanno saggiamente scelto di aggiungere registri separati sui processori più recenti piuttosto che aggiungere registri più sovrapposti.

(E sì, ciò significa che è davvero più veloce sui processori moderni " MOVZX EAX, valore " esplicitamente, che farlo nel modo più vecchio e sciatto di " MOV AXE, valore / uso EAX " ;.)

Conclusione

Detto questo, Intel e AMD potrebbero aggiungere più "sovrapposizione" registra se lo volessero davvero? Sicuro. Ci sono modi per inserirli se c'è abbastanza domanda. Ma dato il notevole bagaglio storico, le attuali limitazioni architettoniche, le notevoli limitazioni delle prestazioni e il fatto che la maggior parte del codice in questi giorni è generata da compilatori ottimizzati per i registri non sovrapposti, è altamente improbabile che aggiungano queste cose presto.

Nei vecchi giorni a 8 bit, c'era il registro A.

Nei giorni a 16 bit, c'era il registro AX a 16 bit, che era diviso in due parti a 8 bit, AH e AL, per quei momenti in cui si voleva ancora lavorare con valori a 8 bit.

Nei giorni a 32 bit, è stato introdotto il registro EAX a 32 bit, ma i registri AX, AH e AL sono stati tutti mantenuti. I progettisti non hanno ritenuto necessario introdurre un nuovo registro a 16 bit che indirizzava i bit da 16 a 31 di EAX.

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