1.09 Lezione 9 - follen99/ArchitetturaDeiCalcolatori GitHub Wiki

🏁 0:25 03-25

Altre istruzioni RISC

Il RISC ha un set di istruzioni componibile; per progettare questo set di istruzioni ci si è accorti dei vari errori compiuti con il designing del precedente processore (MIPS).

Nel set di istruzioni di base di un processore, è strettamente necessario avere operazioni come la moltiplicazione?

Ci si è posti questa domanda proprio perchè il precedente processore (MIPS), nato per essere usato intensivamente su macchine potenti, è finito per essere utilizzato nelle centraline come quelle delle lavatrici;

Si capisce quindi che è inutile avere un set di istruzioni ricco (come ad esempio la moltipliazione) in un processore che poi viene utilizzato poco.

Inoltre il processore può essere riadattato all'utilizzo di istruzioni compresse, ovvero a 16 bit; questo è il motivo per cui i registri sono disposti in modo strano.

Fine capitolo 2

Confutiamo qualche credenza

Avere delle istruzioni più potenti non significa avere prestazioni migliori; questo perchè le istruzioni più complesse sono più difficili da implementare in maniera efficiente. Inoltre capita che le istruzioni complesse rallentano le altre, quindi è molto meglio usare un set di istruzioni più semplici e far ottimizzare il tutto al compilatore.

🏁 0:33

Le istruzioni più complesse aiuterebbero sicuramente il programmatore a scrivere un programma più compatto, ma siccome ai nostri giorni la programmazione assembly è utilizzata solo quando si è costretti (ad esempio quando dobbiamo lavorare direttamente sui registri), vengono scritti solo piccoli pezzi di codice, e quindi è meglio ottimizzare che facilitare il programmatore.

Estendere il set di istruzioni

I processori vengono progettati con un certo set di istruzioni, ma nulla vieta ai programmatori di aggiungerne altre con il tempo. L'obbiettivo dei progettisti del RISC è proprio questo.

🏁 0:41

fine capitolo 2


Capitolo 3 : Aritmetica per computers

Addizione ad interi

Abbastanza semplice, già visto in altri corsi e non mi dilungo.

Fare qualche esercizio per essere sicuro.

Sottrazione ad interi

Per quanto riguarda la sottrazione, invece di effettuare realmente la sottrazione, ci basta fare un'addizione con il numero da sottrarre negativo;

Quindi ci basta fare cambiare il segno del numero da sottrarre, e quindi addizionarlo al primo.

7-6 = 7 + (-6)

Ricordiamo che il complemento a 2 ci basta invertire bit a bit il numero, e poi sommare 1.

Ho un Overflow quando ho due numeri che una volta cambiato il segno questi due sono di segno opposto e sopratutto ottengo come risultato 0.

Perchè?

Questo perchè storicamente i primi processori erano fatti a risparmio e quindi si cercava di limitare i componenti hardware che potevano essere sostituiti dal software.

Moltiplicazione di interi

Anche in questo caso questa è già stata vista in altri esami, non mi dilungo.

Fai qualche esercizio per sicurezza.

Pipelining

Un moltiplicatore particolarmente veloce è ottenuto utilizzando la tecnica del pipelining; questo vuol dire usare l'output di un adder come input di un altro, in modo da poter ottimizzare l'operazione.

Ottimizzazioni varie

Abbiamo detto che quando il compilatore trova una moltiplicazione per potenza di 2, invece di moltiplicare, effettua uno shift, in modo da risparmiare molto tempo.

Oltre a fare questo, quando non abbiamo una vera e propria potenza di due, come ad esempio 12, il compilatore potrebbe, invece di moltiplicare, eseguire uno shift di due volte, uno shift di tre volte e sommo i due numeri ottenuti.

Moltiplicazione in RISC

  • mul restituisce solo gli ultimi 64 bit della moltiplicazione; se c'è un overflow non ci viene restituito alcun errore, e probabilemnte il risultato è sbagliato.
  • mulh - multiply high, ovvero ci restituisce i 64 bit più alti; entrambe mulh e mul lavorano per numeri rappresentati a complemento a due (1 in testa significa numero molto grande, e non negativo in unsigned) usato quando entrambi gli operandi sono con segno
  • mulhu queste due operazioni servono per i numeri unisgned usato quando entrambi gli operandi sono senza segno
  • mulhsu quando un operando è con segno e l'altro no.

Divisione

Video disponibile qui

Fare la divisione è una discreta perdita di tempo, questo è il motivo per cui le istruzioni di divisione, sono sempre composte da un numero di cicli di clock molto elevato.

Fortunatamente le divisioni sono discretamente rare nei programmi, inoltre i compilatori fanno di tutto per evitarle, in modo da trasformarle in qualche altra operazione che dia lo stesso risultato.

Divisore ottimizzato

Non possiamo usare hardware parallelo come abbiamo visto nel moltiplicatore.

Quindi, i divisori veloci, generano quozienti multipli step by step; questo non risolve il problema più di tanto.

Divisione in RISC

Quattro istruzioni:

  • div, rem: divisione e reminder
  • divu e remu: stesse istruzioni, usate per gli unsigned

Attenzione! non viene effettuato alcun controllo sugli overflow, questo come al solito per andare a sparagno.

Floating Point

Rappresentazione per i numeri non interi;

Un intero è rappresentato senza errori, se ad esempio int = 3, quell'intero vale 3 e basta, senza una parte dopo la virgola.

Gli interi rappresentati in informatica, sono ovviamente non infiniti. A patto di rimanere nel range degli interi rappresentabili, valgono le solite proprietà: associativa, commutativa, ecc...

Il problema rimane sempre il solito, tutti i numeri sono invertibili, tranne il most neg, che non ha il corrispettivo positivo (sempre per la solita storia). Se neghiamo il most neg, otteniamo lo stesso numero, bel problema!

Numeri reali

Esempi: numeri come la virgola, come 2.15, 5.27 ...

Non posso rappresentare questi numeri come gli interi, proprio perchè mi servirebbe una stringa potenzialmente infinita per rappresentare i numeri reali.

Per forza di cose, nei calcolatori, i numeri reali saranno sempre affetti da un, seppur minimo, errore.

L'errore è molto piccolo rispetto alla grandezza del numero in sé, ma c'è sempre. L'obbiettivo è quello di sbagliare di molto con i numeri grandi, ma sbagliare poco con i numeri piccoli.

La rappresentazione in virgola mobile, tenta proprio di comportarsi in questo modo; cioè tenta di aumentare le possibili configurazioni (precisione del valore) nelle posizioni più vicine allo zero, e diminuire la precisione nelle posizioni più lontane dallo zero.


fine lezione 9

⚠️ **GitHub.com Fallback** ⚠️