Poiché un sistema a 32 bit non è in grado di gestire un numero 2 ^ 33 (a causa dell'ovvio limite a 32 bit), come può gestire un numero in virgola mobile a 80 bit ?
Dovrebbe richiedere "80-bit" ...
Poiché un sistema a 32 bit non è in grado di gestire un numero 2 ^ 33 (a causa dell'ovvio limite a 32 bit), come può gestire un numero in virgola mobile a 80 bit ?
Dovrebbe richiedere "80-bit" ...
Risposte:
Uno dei significati di una CPU a 32 bit è che i suoi registri sono larghi 32 bit. Ciò non significa che non possa gestire i numeri di 64 bit, ma solo che deve occuparsi prima della metà inferiore a 32 bit, quindi della seconda metà superiore a 32 bit. (È per questo che le CPU hanno un flag carry .) È più lento che se la CPU potesse semplicemente caricare i valori in un registro più ampio a 64 bit, ma è ancora possibile.
Pertanto, il "testimone" di un sistema non limita necessariamente la dimensione dei numeri che un programma può gestire, poiché è sempre possibile interrompere le operazioni che non rientrano nei registri della CPU in più operazioni. Quindi rende le operazioni più lente, consuma più memoria (se devi usare la memoria come "scratchpad") e più difficile da programmare, ma le operazioni sono ancora possibili.
Tuttavia, nulla di tutto ciò conta, ad esempio, con processori Intel a 32 bit e virgola mobile, poiché la parte in virgola mobile della CPU ha i suoi registri e sono larghi 80 bit. (All'inizio della storia dell'x86, la capacità in virgola mobile era un chip separato, era integrato nella CPU a partire da 80486DX.)
La risposta di @ Breakthrough mi ha ispirato ad aggiungere questo.
I valori in virgola mobile, nella misura in cui sono memorizzati nei registri FPU, funzionano in modo molto diverso dai valori interi binari.
Gli 80 bit di un valore in virgola mobile sono divisi tra una mantissa e un esponente (c'è anche la "base" nei numeri in virgola mobile che è sempre 2). La mantissa contiene le cifre significative e l'esponente determina quanto sono grandi quelle cifre significative. Quindi non c'è "overflow" in un altro registro, se il tuo numero diventa troppo grande per adattarsi alla mantissa, il tuo esponente aumenta e perdi precisione - cioè quando lo converti in un numero intero, perdi i decimali a destra - ecco perché si chiama virgola mobile.
Se il tuo esponente è troppo grande, hai un overflow in virgola mobile, ma non puoi facilmente estenderlo ad un altro registro poiché l'esponente e la mantissa sono legati insieme.
Potrei essere inesatto e sbagliato su un po 'di questo, ma credo che sia questo il senso. (Questo articolo di Wikipedia illustra un po 'più succintamente quanto sopra).
Va bene che questo funziona in modo totalmente diverso dal momento che l'intera parte "a virgola mobile" della CPU è in un certo senso nel suo mondo: per accedervi e usi simili istruzioni CPU speciali. Inoltre, verso il punto della domanda, poiché è separato, il testimone della FPU non è strettamente associato al testimone della CPU nativa.
-fomit-frame-pointer
per riavere quel registro.
32-bit, 64-bit e 128-bit si riferiscono tutti alla lunghezza della parola del processore, che può essere considerata il "tipo di dati fondamentale". Spesso, questo è il numero di bit trasferiti da / verso la RAM del sistema e la larghezza dei puntatori (anche se nulla ti impedisce di utilizzare il software per accedere a più RAM di quello a cui un singolo puntatore può accedere).
Supponendo che una velocità di clock costante (così come tutto il resto nell'architettura sia costante) e supponendo che letture / scritture di memoria abbiano la stessa velocità (ipotizziamo 1 ciclo di clock qui, ma questo è lontano dal caso nella vita reale), puoi aggiungi due numeri a 64 bit in un singolo ciclo di clock su un computer a 64 bit (tre se conti il recupero dei numeri dalla RAM):
ADDA [NUM1], [NUM2]
STAA [RESULT]
Possiamo anche fare lo stesso calcolo su una macchina a 32 bit ... Tuttavia, su una macchina a 32 bit, dobbiamo farlo nel software, poiché prima devono essere aggiunti i 32 bit inferiori, compensare l'overflow, quindi aggiungere i 64 bit superiori:
ADDA [NUM1_LOWER], [NUM2_LOWER]
STAA [RESULT_LOWER]
CLRA ; I'm assuming the condition flags are not modified by this.
BRNO CMPS ; Branch to CMPS if there was no overflow.
ADDA #1 ; If there was overflow, compensate the value of A.
CMPS ADDA [NUM1_UPPER], [NUM2_UPPER]
STAA [RESULT_UPPER]
Analizzando la mia sintassi dell'assembly inventato, puoi facilmente vedere come operazioni di precisione più elevata possono richiedere un tempo esponenzialmente più lungo su una macchina di lunghezza inferiore. Questa è la vera chiave dei processori a 64 e 128 bit: ci consentono di gestire un numero maggiore di bit in una singola operazione. Alcune macchine includono istruzioni per aggiungere altre quantità con un carry (ad esempio ADC
su x86), ma l'esempio sopra ha in mente valori di precisione arbitrari.
Ora, per estenderlo alla domanda, è semplice vedere come potremmo aggiungere numeri più grandi dei registri che abbiamo a disposizione - abbiamo semplicemente suddiviso il problema in blocchi delle dimensioni dei registri e lavoriamo da lì. Sebbene, come menzionato da @MatteoItalia , lo stack FPU x87 abbia un supporto nativo per quantità a 80 bit, nei sistemi privi di questo supporto (o nei processori privi di un'unità in virgola mobile!), I calcoli / operazioni equivalenti devono essere eseguiti nel software .
Quindi, per un numero a 80 bit, dopo aver aggiunto ciascun segmento a 32 bit, verificherebbe anche l'overflow nel bit 81 e, se lo si desidera, azzerare i bit di ordine superiore. Questi controlli / zeri vengono eseguiti automaticamente per determinate istruzioni x86 e x86-64, dove vengono specificate le dimensioni degli operandi di origine e destinazione (sebbene siano specificate solo in potenze di 2 a partire da 1 byte di larghezza).
Naturalmente, con numeri in virgola mobile, non si può semplicemente eseguire l'aggiunta binaria poiché la mantissa e le cifre significative sono raggruppate insieme in forma offset. Nell'ALU su un processore x86, esiste un circuito hardware per eseguire ciò per i float IEEE a 32 e 64 bit; tuttavia , anche in assenza di un'unità a virgola mobile (FPU), gli stessi calcoli possono essere eseguiti nel software (ad esempio mediante l'uso della GNU Scientific Library , che utilizza una FPU quando compilata su architetture con, ripiegando su algoritmi software se non è disponibile alcun hardware in virgola mobile [ad es. per microcontrollori incorporati privi di FPU]).
Data la memoria sufficiente, si possono anche eseguire calcoli su numeri di precisione arbitraria (o "infinita" - entro limiti realistici), usando più memoria poiché è richiesta maggiore precisione. Un'implementazione di questo esiste nella libreria GNU Multiple Precision , che consente una precisione illimitata (fino a quando la RAM non è piena, ovviamente) su operazioni a numero intero, razionale e in virgola mobile.
L'architettura di memoria del sistema può consentire solo di spostare 32 bit contemporaneamente, ma ciò non gli impedisce di utilizzare numeri più grandi.
Pensa alla moltiplicazione. Potresti conoscere le tue tabelle di moltiplicazione fino a 10x10, ma probabilmente non avrai problemi a eseguire 123x321 su un pezzo di carta: lo spezzerai in molti piccoli problemi, moltiplicando le singole cifre e occupandoti del trasporto ecc.
I processori possono fare la stessa cosa. Ai vecchi tempi c'erano processori a 8 bit che potevano fare matematica in virgola mobile. Ma erano slooooooow.
"32-bit" è davvero un modo di classificare i processori, non una sentenza set-in-stone. un processore "32 bit" in genere ha registri per scopi generali a 32 bit con cui lavorare.
Tuttavia, non esiste un requisito fondamentale per l'esecuzione di tutto nel processore a 32 bit. Ad esempio, non era inaudito che un computer a "32 bit" avesse un bus di indirizzo a 28 bit, perché era più economico realizzare l'hardware. I computer a 64 bit spesso hanno solo un bus di memoria a 40 o 48 bit per lo stesso motivo.
L'aritmetica in virgola mobile è un altro luogo in cui le dimensioni variano. Molti processori a 32 bit supportano numeri in virgola mobile a 64 bit. Lo hanno fatto memorizzando i valori in virgola mobile in registri speciali che erano più ampi dei registri di uso generale. Per memorizzare uno di questi grandi numeri in virgola mobile nei registri speciali, si dovrebbe prima dividere il numero tra due registri di uso generale, quindi emettere un'istruzione per combinarli in un galleggiante nei registri speciali. Una volta in quei registri a virgola mobile, i valori sarebbero manipolati come float a 64 bit, piuttosto che come una coppia di metà a 32 bit.
L'aritmetica a 80 bit che citi è un caso speciale di questo. Se hai lavorato con numeri in virgola mobile, hai familiarità con l'imprecisione derivante da problemi di arrotondamento in virgola mobile. Una soluzione per il roundoff è quella di avere più bit di precisione, ma poi è necessario memorizzare numeri più grandi e forzare gli sviluppatori a utilizzare valori in virgola mobile insolitamente grandi in memoria.
La soluzione Intel è che i registri a virgola mobile sono tutti a 80 bit, ma le istruzioni per spostare i valori da / verso quei registri funzionano principalmente con numeri a 64 bit. Finché si opera interamente all'interno dello stack Intel a virgola mobile x87, tutte le operazioni vengono eseguite con 80 bit di precisione. Se il codice deve estrarre uno di quei valori dai registri a virgola mobile e memorizzarlo da qualche parte, lo tronca a 64 bit.
Morale della storia: categorizzazioni come "32-bit" sono sempre più sfocate quando si approfondiscono le cose!
Una CPU a "32 bit" è quella in cui la maggior parte dei registri dei dati sono registri a 32 bit e la maggior parte delle istruzioni opera sui dati in quei registri a 32 bit. È anche probabile che una CPU a 32 bit trasferisca i dati da e verso la memoria a 32 bit alla volta. La maggior parte dei registri essendo a 32 bit non significa che tutti i registri siano a 32 bit. La risposta breve è che una CPU a 32 bit può avere alcune funzionalità che utilizzano altri conteggi, come i registri a virgola mobile a 80 bit e le istruzioni corrispondenti.
Come ha detto @spudone in un commento sulla risposta di @ ultrasawblade, la prima CPU x86 ad avere operazioni in virgola mobile integrate è stata Intel i486 (in particolare l'80486DX ma non l'80486SX), che, secondo la pagina 15-1 dei programmatori a microprocessore i486 Manuale di riferimento , include nei suoi registri numerici "Otto registri numerici a 80 bit indirizzabili individualmente". L'i486 ha un bus di memoria a 32 bit, quindi il trasferimento di un valore di 80 bit richiederebbe 3 operazioni di memoria.
Il predecessore della generazione 486, l'i386, non aveva alcuna operazione in virgola mobile integrata. Invece, aveva il supporto per l'uso di un "coprocessore" a virgola mobile esterno, l'80387. Questo coprocessore aveva quasi la stessa funzionalità integrata nell'i486, come si può vedere dalla pagina 2-1 del Manuale di riferimento del programmatore 80387 .
Il formato a virgola mobile a 80 bit sembra aver avuto origine con l'8087, il coprocessore matematico per 8086 e 8088. Gli 8086 e 8088 erano CPU a 16 bit (con bus di memoria a 16 e 8 bit), ed erano ancora in grado utilizzare il formato a virgola mobile a 80 bit, sfruttando i registri a 80 bit nel coprocessore.