Istruzioni logiche

Shift logico
...

  • A sinistra
  • A destra

Shift logico a sinistra
...

L'operazione si chiama shift left logical e si indica con sll.
Non è altro che l'operazione di shift a sinsitra.
Pasted image 20230318182811.png
sll x9, x22, x19 (shift di una sola posizione)
x9 = x22 << x19

Versione immediata: shift left logical immediate
slli x9, x22, 5 (shift di 5 posizioni)
x9 = x22 << 5

Shift logico a destra
...

L'operazione si chiama shift right logical e si indica con srl.
Non è altro che l'operazione di shift a sinsitra.
Pasted image 20230318183051.png
srl x9, x22, x19 (shift di una sola posizione)
x9 = x22 >> x19

Versione immediata: shift right logical immediate
srli x9, x22, 5 (shift di 5 posizioni)
x9 = x22 >> 5

Shift aritmetico
...

Lo shift aritmetico è uguale allo shift logico, solo che con questa operazione, il bit più significativo viene mantenuto, mentre quello meno significativo viene sostituito con un bit nullo (0).

  • A sinistra non esiste poiché non ha senso (è come l'operazione sll)
  • A destra

Shift aritmetico a destra
...

Può essere sia positivo, quando il bit più significativo è 0, o negativo, quando il bit più significativo è 1.
L'operazione si chiama shift right arithmetic e si indica con sra ed srai la sua versione immediata.
sra x9, x22, x19
x9 = x22 >> x19

srai x9, x22, 5
x9 = x22 >> 5

Le istruzioni sll, srl, sra si rappresentano in linguaggio macchina con il formato R. Mentre slli, srli, srai si rappresentano in linguaggio macchina con il formato I (vengono utilizzati 6 bit meno significativi del campo immediato per codificare la costante, gli altri sono posti a zero).
Come sappiamo lo shift a sinistra di i posizioni calcola una moltiplicazione per , mentre lo shift a destra aritmetico di i posizioni calcola una divisione intera per .

Esempio
...

long i, j;
long v[10];
// altro codice
v[i] = v[j];
long i, j;
long v[10];
// altro codice
v[i] = v[j];

Posti: i = x9; j =x21; v = x19;

//v[j]
addi x6, x21, 0
slli x6, x6, 3
add x6, x6, x19
ld x6, 0(x6)
//v[i]
addi x7, x9, 0
slli x7, x7, 3
add x7, x7, x19
sd x6, 0(x7)
//v[j]
addi x6, x21, 0
slli x6, x6, 3
add x6, x6, x19
ld x6, 0(x6)
//v[i]
addi x7, x9, 0
slli x7, x7, 3
add x7, x7, x19
sd x6, 0(x7)
long i, j;
long v[10];
// altro codice
v[i] = v[j];

Posti: i = x9; j =x21; v = x19;

//v[j]
addi x6, x21, 0
slli x6, x6, 3
add x6, x6, x19
ld x6, 0(x6)
//v[i]
addi x7, x9, 0
slli x7, x7, 3
add x7, x7, x19
sd x6, 0(x7)

=== end-multi-column

NOTA il codice assembly si riferisce SOLO all'assegnamento v[i] = v[j].

Per calcolare v[j]:
j è una variabile che contiene un valore.
Con la prima riga di assembly, viene salvato il contenuto di x21 nel registro x6.
Viene fatto uno shift a sinistra (ovvero una moltiplicazione per dove in questo caso) del contenuto del registro x6.

Perché viene fatta questa cosa?

x6 prende il valore di x21 (j), sapendo di doversi spostare alla j-esima posizione di memoria del vettore v e sapendo che v è un vettore di long, il che vuol dire che ogni posizione dell'array v avrà dimensione di una double word, che è 8 byte e che è , allora viene fatto uno shift a sinistra di 3. É come se j indicasse il numero della posizione all'interno di v, ma bisogna far in modo che ogni posizione sia grande .
Infatti nella riga: add x6, x6, x19: x6 viene utilizzato come scostamento all'interno di x19 (che ricordiamo salva solo l'indirizzo base di v, ovvero v[0]). A questo punto x6 contiene l'indirizzo esatto di della posizione j di v.

Infatti nella riga: add x6, x6, x19: x6 viene utilizzato come scostamento all'interno di x19 (che ricordiamo salva solo l'indirizzo base di v, ovvero v[0]). Questa operazione salva in x6, la somma tra x19 e x6, ovvero, a questo punto x6 contiene l'indirizzo esatto di della posizione j di v.
Nella riga: ld x6, 0(x6): viene fatto un caricamento dalla memoria:

  • da dove? Da 0(x6) che non è altro che v[j].
  • verso dove? Verso x6 stesso
    Alla fine di questa operazione x6 conterrà il valore che è presente in v[j]

Operazioni analoghe vengono fatte per v[i] usando come registro x7.

Ultima riga da analizzare: sd x6, 0(x7), x7 contiene l'indirizzo della posizione i di v.
La riga assembly effettua uno store in memoria:

  • da dove? Viene preso il valore del registro x6 (v[j])
  • verso dove? Verso x7 che contiene l'indirizzo di v[i].

NOTA: nella parte di codice per v[i] manca il load dalla memoria, che consente ad x6 di contenere il valore di v[j] e non il suo indirizzo, come invece è per x7, in cui questa operazione di caricamento dalla memoria non viene fatta.