Istruzioni base Assembly RISC-V

Argomenti trattati:

  1. Prima parte:teoria, formato delle istruzioni, cosa accade in memoria e nella CPU
  1. Seconda parte:istruzioni, come utilizzarle

PRIMA PARTE

Ci sono delle direttive all’assembler che rendono il codice assembly più espressivo e leggibile.

.text #indica che le linee successive contengono istruzioni o dati
.data #idem

.align n # indica l'allineamento su n byte

.globl main #etichetta main è globale,quindi visibile da altri file

.asciiz #area di memoria che memorizza una stringa terminata da NULL

.text permette di usare delle etichette, per indicare porzioni di codice, un po come il goto del C.

.align indica l’allineamento su n byte, cioè l’istruzione una volta messa in memoria deve cominciare da un indirizzo che è un multiplo di 2^n.Quindi tutte le istruzioni che seguono devono essere posizionate in memoria centrale in un indirizzo multiplo di 2^n.

.globl main indica che questa posizione di memoria puo essere usata anche in altre unità del programma stesso.L’istruzione .globl indica che il simbolo main sarà accessibile anche dall’esterno del file.

.asciiz “SIMBOLI” significa che ciascuno dei simboli verra rappresentato con un byte in memoria cosi come vuole la codifica ASCII e verrà terminato con un byte a zero.

Le istruzioni comprese nel linguaggio macchina di qualsiasi computer sono classificabili in 4 categorie:

Non essendoci cicli come il for, while ecc… posso ricrearle tramite le istruzioni che modificano il program counter.

I 32 registri di RISC-V, nominati da 0 a 31, possono essere chiamati con la seguente notazione:

x+NUMERO REGISTRO
----esempio----
x0 #indico il registro 0(che per default ha e mantiene il valore zero)

Per codificarli, essendone 32 bastano 5 bit.

Non confondere variabile con registro: una variabile è un ingombro di memoria caratterizzato da un nome e un tipo, mentre il registro è solo un ingombro che si trova dentro la CPU e non in RAM.

Una word sono 32 bit, una half word sono 16 bit, una double word sono 64 bit.Quindi i registri contengono un ingombro di una double word.

Un’istruzione che prova a modificare x0 non ha alcun effetto:x0 mantiene il valore di default 0.

I registri si possono anche chiamare con nomi simbolici che specificano l’utilizzo(n.b. i registri sono general purpose, quindi si possono utilizzare come si preferisce):

ci sono registri che non possono essere chiamati e non si puo operare al loro interno:

REGISTRI NON REFERENZIABILI
hi, lo Registri per moltiplicazioni e divisioni
pcProgram Counter

Il formato dell’istruzione significa guardare quei 32 bit di cui è composta l’istruzione assembly e guardare quindi i suoi campi.

rs è il registro sorgente(esempio gli addendi di una addizione), rd(dove il risultato va salvato) è il registro destinazione.

L’immediate è una costante, quindi un valore numerico che si scrive direttamente nell’istruzione.

Ogni istruzione può al massimo:

Ecco i 6 tipi di formato di istruzioni in assembly RISC-V:

ATTENZIONE:

  1. in load e store l’immediate è un offset rispetto a un registro base per individuare l’indirizzo di memoria centrale riferito al dato.
  1. in branch and jump è un offset rispetto al program counter o un altro registro per individuare l’indirizzo di memoria dell’istruzione destinazione del salto.
ℹ️
siccome gli indirizzi di memoria sono a 64 bit, la massima RAM che si può avere è 2^64,cioè 2147483639.42 Gibibytes,praticamente irragiungibile


SECONDA PARTE

Istruzioni aritmetico-logiche

Il fatto di avere solo due operazioni semplifica l’HW ma complica alcuni aspetti.

SOMMA

add x2,x4,x7

questa operazione esegue l’addizione tra il contenuto di x4,x7 e poi lo salva(store) in x2.

SOTTRAZIONE

sub x2,x4,x7 #x4-x7 e salva il tutto in x2

Trasferimento da o verso memoria

Sono istruzioni che si occupano di trasferire dati dalla memoria centrale ai registri(load-ld) o viceversa(store-st).

formato: OPERATORE registro indirizzo memoria

ld sta per load double(double word), mentre sd store double.

LOAD

l'istruzione di load trasferisce una copia della parola contenuta in una specifica locazione di memoria (a 64 bit) mettendola in un registro della CPU, e lasciando inalterata la parola di memoria:

la memoria è vista come un array di celle.Leggere una locazione di memoria significa richiederne una copia e trasferirla in CPU.

La locazione di memoria è indicata con la modalità BASE REGISTER + OFFSET

STORE

E’ la duale della load, solo che avrò un registro sorgente anzichè un indirizzo destinazione.

L'istruzione di store trasferisce una parola da un registro della CPU (64 bit) mettendola in una specifica locazione di memoria, sovrascrivendo il contenuto precedente di quella locazione:

🔥
PSEUDO ISTRUZIONI:sono delle istruzioni che non esistono nella ISA RISC-V, però è l’assemblatore che la traduce in una sequenza di una o più istruzioni native.

Pseudo-istruzioni

CARICAMENTO DI COSTANTE O DI INDIRIZZO

li t0 , 4      #carica la costante 4 in t0 (load immediate)
la a0, LABEL   #carica l'indirizzo LABEL in a0 (load address)

LABEL serve ad indicare il valore dell’indirizzo di memoria di un dato.

La load immediate consente di caricare una costante da 32 bit anzichè una da 20.

La differenza tra la e ld è che la trasferisce un indirizzo, mentre ld il contenuto in quell’ingombro.

Quindi le pseudo istruzioni vengono estese dall’assembler in quanto non sono presenti nella CPU in origine.

Istruzioni di Salto

SALTO CONDIZIONATO:

SALTO INCONDIZIONATO CON COLLEGAMENTO:

il calcolo dell’indirizzo destinazione di salto è relativo (a PC o rs1)
• identificato da uno
spiazzamento in CPL2: 12 bit per i formati B e I,
e
20 bit per il formato J
l’indirizzo di un’istruzione è a parola, ossia è sempre multiplo di 4
• convenzioni e operazioni HW apposite assicurano che la somma di
registro base
e spiazzamento
produca sempre un indirizzo di istruzione che sia multiplo di 4.

formato
beq, bne, bge, bltB
jump & link: jalJ
jal da registro: jalrI

FORMATO B

– opcode:(opcode) identifica il tipo di istruzione
– rs1:primo operando sorgente
– rs2: secondo operando sorgente (dato da scrivere in memoria)
– funct3: indicano la variante specifica dell’istruzione per effettuare
il confronto tra rs1 e rs2
– imm[12:1]:valore ricostruito dello spiazzamento su 12 bit in CPL2

lo spiazzamento (rispetto al PC) ha a disposizione solo 12 bit in questo formato deve fare riferimento ad half word (mezza parola), pertanto esso termina sempre con un bit 0 che viene sottointeso nella rappresentazione binaria, consentendo di raddoppiare lo spazio di offset
il modulo HW
ESTENSIONE DEL SEGNO, durante la fase di decodifica del codice operativo, ri-costruisce l’offset da 12 bit, lo prolunga fino a 64 bit mediante estensione del segno e aggiunge il bit 0 finale (meno significativo) sottointeso nella rappresentazione binaria dell’istruzione (nella figura si vede estensione a 32 bit).

Prima di sommare l’offset al PC, il processore riporta a byte l’offset (già esteso in segno) tramite moltiplicazione per due(scorrimento a sx di una posizione e aggiunta di un bit 0 a dx).

l’indirizzamento relativo al Program Counter permette di fare salti condizionati ad aree di memoria il cui indirizzo non è esprimibile con solo 12 bit.

esempio: bne s0, s1, L1 #esegui e vai a L1 se il contenuto di s0 è != da quello di s1

– per esprimere l’etichetta L1 si dispone solo di 12 bit
– ⇒ il valore di L1 è calcolato rispetto al Program Counter in modo da saltare di 2^12 mezze parole avanti o indietro rispetto all’istruzione corrente

(per il principio di località degli indirizzi di memoria è utile calcolare l’indirizzo di destinazione del salto come offset rispetto all’istruzione corrente)

Per permettere salti in avanti e indietro, l’offset è rappresentato in complemento a 2.

l’assemblatore sostituisce l’etichetta L1 con lo spiazzamento
alla mezza parola relativo a PC: (L1− PC) / 2, dove
– PC contiene l’indirizzo dell’istruzione di salto
– la divisione per due serve per calcolare l’indirizzo di mezza parola

Il valore del campo indirizzo può anche essere negativo(salto all’indietro).

FORMATO J

Lo spiazzamento rispetto al PC ha a disposizione solo 20 bit e deve fare riferimento a half word.Pertanto esso termina sempre con un bit 0 che viene sottointeso nella rappresentazione binaria, consentendo di raddoppiare lo spazio di offset il modulo HW ESTENSIONE DEL SEGNO, durante la fase di decodifica del codice operativo, ri-costruisce l’offset da 20 bit, lo prolunga fino a 64 bit mediante estensione del segno e aggiunge il bit 0 finale (meno significativo) sottointeso nella rappresentazione binaria dell’istruzione (nella figura si vede estensione a 32 bit).

pertanto, prima di sommare l’offset al PC, il processore riporta a byte l’offset (già esteso in segno) tramite moltiplicazione per due(scorrimento a sx di una posizione e aggiunta di un bit 0 a dx).

Dichiarazione di una costante

•eqv NUM1, 200 # come "#define NUM1 100" in C

Come memorizzare una costante da 8 byte?

Dipende, posso utilizzare due convenzioni:

RISC-V UTILIZZA LITTLE ENDIAN come endianess.

Altre istruzioni

N.b. il NOT è una pseudoistruzione