La maggior parte del contenuto di questa risposta proveniva originariamente da questa risposta (scritta prima che l'altra domanda fosse segnata come un duplicato). Quindi discuto l'uso di valori a 8 bit (anche se questa domanda riguardava valori a 32 bit), ma va bene perché i valori a 8 bit sono più semplici da capire concettualmente, e gli stessi concetti si applicano a valori più grandi come l'aritmetica a 32 bit.
Quando si aggiungono due numeri che sono a 8 bit, il numero più grande che si può ottenere (0xFF + 0xFF = 1FE). Infatti, se si moltiplicano due numeri che sono a 8 bit, il numero più grande che si può ottenere (0xFF * 0xFF = 0xFE01) è ancora 16 bit, due volte di 8 bit.
Ora, si può supporre che un processore x-bit possa tenere traccia solo degli x-bit. (Per esempio, un processore a 8 bit può tenere traccia solo di 8 bit). Il processore a 8 bit riceve i dati in blocchi di 8 bit (questi “blocchi” hanno tipicamente un termine formale: “parola”. Su un processore a 8 bit si usano parole a 8 bit. Su un processore a 64 bit, si possono usare parole a 64 bit.)
Quindi, quando si danno al computer 3 byte:
Byte #1: l'istruzione MUL
Byte #2: i byte di ordine elevato (ad esempio, 0xA5)
Byte #3: i byte di ordine inferiore (ad esempio, 0xCB)
Il computer può generare un risultato che è superiore a 8 bit. La CPU può generare risultati come questo:
0100 0000 0100 0010 xxxx xxxx xxxx xxxx xxxx xxxx 1101 0111
a.k.a.:
0x4082xxxxxxD7
Ora, lasciatemi interpretare questo per voi:
0x significa solo che le seguenti cifre sono esadecimali.
Parlerò brevemente del “40” in dettaglio.
82 fa parte del registro “A”, che è una serie di 8 bit.
xx e xx fanno parte di altri due registri, denominati registro “B” e registro “C”. Il motivo per cui non ho riempito quei bit con zeri o uno è che un'istruzione “ADD” (inviata alla CPU) può far sì che quei bit rimangano invariati dall'istruzione (mentre la maggior parte degli altri bit che uso in questo esempio possono essere alterati, ad eccezione di alcuni dei flag bit).
D7 entrerebbe in più bit, chiamato registro “D”.
Un registro è solo un pezzo di memoria. I registri sono integrati nelle CPU, quindi la CPU può accedere ai registri senza dover interagire con la memoria su una chiavetta RAM.
Quindi il risultato matematico di 0xA5 volte 0xCB è 0x82D7.
Ora, perché i bit sono stati divisi nei registri A e D invece che nei registri A e B, o nei registri C e D? Bene, ancora una volta, questo è uno scenario di esempio che sto usando, pensato per essere piuttosto simile in concetto ad un vero e proprio linguaggio Assembly (Intel x86 16-bit, come usato dagli Intel 8080 e 8088 e molte CPU più recenti). Ci potrebbero essere alcune regole comuni, come il registro “C” usato tipicamente come indice per le operazioni di conteggio (tipico per i loop), e il registro “B” usato per tenere traccia degli offset che aiutano a specificare le posizioni di memoria. Quindi, “A” e “D” possono essere più comuni per alcune delle funzioni aritmetiche comuni.
Ogni istruzione della CPU dovrebbe avere una certa documentazione, usata da chi programma in Assembly. Tale documentazione dovrebbe specificare quali registri vengono utilizzati da ciascuna istruzione. (Quindi la scelta di quali registri utilizzare è spesso specificata dai progettisti della CPU, non dai programmatori del linguaggio Assembly. Anche se ci può essere una certa flessibilità).)
Ora, tornando al “40” nell'esempio precedente: si tratta di una serie di bit, spesso chiamati “flag register”. Ogni bit del registro delle bandiere ha un nome. Per esempio, c'è un bit “overflow” che la CPU può impostare se il risultato è più grande dello spazio che può memorizzare un byte dei risultati. (Il bit “overflow” può essere spesso indicato con il nome abbreviato di “OF”. Si tratta di una “o” maiuscola, non di uno zero). Il software può controllare il valore di questo flag e notare il “problema”. Lavorare con questo bit è spesso gestito in modo invisibile da linguaggi di livello superiore, quindi i programmatori principianti spesso non imparano ad interagire con i flag della CPU. Tuttavia, i programmatori di assembly possono comunemente accedere ad alcuni di questi flag in modo molto simile ad altre variabili.
Per esempio, si potrebbero avere più istruzioni ADD. Un'istruzione ADD potrebbe memorizzare 16 bit di risultati nel registro A e nel registro D, mentre un'altra istruzione potrebbe semplicemente memorizzare gli 8 bit bassi nel registro A, ignorare il registro D e specificare il bit di overflow. Quindi, in seguito (dopo aver memorizzato i risultati del registro A nella RAM principale), si potrebbe utilizzare un'altra istruzione ADD che memorizza solo gli 8 bit alti in un registro (possibilmente il registro A.) L'eventuale necessità di utilizzare un flag di overflow può dipendere proprio da quale istruzione di moltiplicazione si utilizza.
(C'è anche comunemente un flag “underflow”, nel caso in cui si sottragga troppo per adattarsi al risultato desiderato)
Giusto per mostrarvi quanto complicate siano diventate le cose:
L'Intel 4004 era una CPU a 4 bit
L'Intel 8008 era una CPU a 8 bit. Aveva registri a 8 bit di nome A, B, C e D.
L'Intel 8086 era una CPU a 16 bit. Aveva registri a 16 bit denominati AX, BX, CX e DX.
L'Intel 80386 era una CPU a 32 bit. Aveva registri a 32 bit denominati EAX, EBX, ECX e EDX.
Le CPU Intel x64 hanno registri a 64 bit denominati RAX, RBX, RCX e RDX. I chip x64 possono eseguire codice a 16 bit (in alcune modalità operative) e possono interpretare istruzioni a 16 bit. In questo modo, i bit che compongono il registro AX sono la metà dei bit che compongono il registro EAX, che sono la metà dei bit che compongono il registro RAX. Quindi, ogni volta che si cambia il valore di AX, si cambia anche EAX e RAX, perché i bit utilizzati da AX fanno parte dei bit utilizzati da RAX. (Se si cambia EAX di un valore che è un multiplo di 65.536, allora i 16 bit bassi sono invariati, quindi AX non cambierebbe. Se si cambia EAX di un valore che non è un multiplo di 65.536, allora anche questo influenzerebbe AX.)
Ci sono più flag e registri di quelli che ho menzionato. Ne ho semplicemente scelti alcuni di uso comune per fornire un semplice esempio concettuale.
Ora, se si è su una CPU a 8 bit, quando si scrive in memoria, si possono trovare alcune restrizioni sulla possibilità di fare riferimento a un indirizzo di 8 bit, non a un indirizzo di 4 bit o 16 bit. I dettagli variano in base alla CPU, ma se si hanno tali restrizioni, allora la CPU potrebbe avere a che fare con parole a 8 bit, ed è per questo che la CPU è più comunemente chiamata “CPU a 8 bit”.